BEM w Vue: struktura stylów dla skalowalnych komponentów
BEM zachowuje aktualność w projektach Vue dzięki ścisłej hierarchii klas, która zapobiega konfliktom stylów w architekturze komponentowej. Vue skupia się na reaktywności i logice, a BEM zapewnia niezależność bloków i elementów. To połączenie minimalizuje bałagan w CSS podczas wzrostu aplikacji.
BEM opiera się na trzech zasadach:
- Blok: niezależna encja jak
.headerlub.card, bez zewnętrznych zależności. - Element: część bloku, oznaczana podwójnym podkreśleniem —
.button__icon. - Modyfikator: wariant lub stan przez pojedyncze podkreślenie —
.button_disabled,.card_theme_dark.
Taka struktura pozwala izolować style, upraszczając debugowanie i refaktoryzację.
Stylizacja w komponentach Vue
W Vue style są pisane wewnątrz <style scoped>, co ogranicza je do zakresu komponentu. Scoped zapobiega wyciekom stylów, ale wymaga ostrożności z zagnieżdżaniem.
:deep() jest stosowane tylko do integracji z zewnętrznymi bibliotekami, gdzie scoped nie radzi sobie. Unikaj go dla omijania własnej architektury — to oznaka problemów w strukturze.
BEM uzupełnia scoped, grupując klasy logicznie. Blok definiuje styl podstawowy, modyfikatory — wariacje, elementy — wewnętrzną strukturę.
Praktyczny przykład: przycisk ze stanami
Bez systemu klasy mnożą się chaotycznie. Rozważ typowy błąd:
<template>
<button :class="{
'button-basic': isBasic,
'button-href': isHref,
'button-avatar': isAvatar
}">
{{ text }}
</button>
</template>
Problemy:
- Brak hierarchii: klasy nie są powiązane z blokiem.
- Skalowanie: nowe stany wymagają dodatkowych warunków.
- Czytelność: z czasem logika ginie.
Z BEM szablon upraszcza się i dokumentuje:
<template>
<button :class="[
'button',
{
'button_disabled': disabled,
'button_loading': loading,
},
{
'button_size_xl': size === 'xl',
'button_size_l': size === 'l',
},
{
'button_primary': color === 'primary',
'button_secondary': color === 'secondary',
}
]">
{{ text }}
</button>
</template>
Klasy są podzielone według semantyki: podstawowy blok, stany, rozmiary, tematy. W CSS:
.button {
/* podstawowe style */
padding: 12px 24px;
border: none;
border-radius: 4px;
}
.button_disabled {
opacity: 0.5;
cursor: not-allowed;
}
.button_loading {
position: relative;
}
.button_primary:not(.button_disabled):hover {
background-color: #0055ff;
}
Selektor :not() filtruje konfliktujące stany bez zbędnych klas.
Skalowanie i praca zespołowa
W dużych projektach BEM redukuje obciążenie kognitywne: developer widzi blok i jego modyfikatory od razu w szablonie. Nie ma potrzeby grzebać w CSS, aby zrozumieć style.
Korzyści w zespole:
- Przewidywalność: nazwy klas odzwierciedlają przeznaczenie.
- Izolacja: bloki nie wpływają na siebie.
- Rozszerzalność: nowe modyfikatory dodawane są bez refaktoryzacji.
Przykład złożonego komponentu — karta produktu z tematami i rozmiarami:
<template>
<div class="card" :class="[
`card_size_${size}`,
`card_theme_${theme}`
]
">
<div class="card__image"></div>
<div class="card__title">{{ title }}</div>
<button class="card__button button">Kup</button>
</div>
</template>
Elementy wewnątrz bloku dziedziczą kontekst, ale pozostają niezależne.
Kiedy zrezygnować z BEM
BEM jest nadmierny dla prototypów lub lądowań: Tailwind lub klasy utility są szybsze. Używaj BEM w projektach z długoterminowym wsparciem, zespołem i złożonym UI.
Co ważne
- BEM uzupełnia Vue, zapewniając ścisłą hierarchię bez konfliktów ze scoped.
- Modyfikatory grupują stany i warianty, upraszczając szablony.
:deep()— tylko dla zewnętrznych bibliotek, nie dla wewnętrznej struktury.- W dużych projektach BEM przyspiesza onboarding i refaktoryzację.
- Testuj na prawdziwym komponencie: czytelność wzrośnie natychmiast.
— Editorial Team
Brak komentarzy.