Особенности CSS в однофайловых компонентах
CSS с ограниченной областью действия
Когда тег <style>
имеет атрибут scoped
, его CSS будет применяться только к элементам текущего компонента. Это похоже на инкапсуляцию стилей в Shadow DOM. Он имеет некоторые оговорки, но не требует полифиллов. Это достигается с помощью PostCSS для преобразования следующих элементов:
vue
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">привет</div>
</template>
В следующие:
vue
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>привет</div>
</template>
Корневые элементы дочерних компонентов
При использовании scoped
стили родительского компонента не будут просачиваться в дочерние компоненты. Однако корневой узел дочернего компонента будет подвержен влиянию как родительского, так и дочернего CSS. Это сделано специально для того, чтобы родитель мог придать стиль дочернему корневому элементу в целях верстки.
Глубокие селекторы
Если вы хотите, чтобы селектор в scoped
стилях был «глубоким», для воздействия на дочерние компоненты, можно использовать псевдокласс :deep()
:
vue
<style scoped>
.a :deep(.b) {
/* ... */
}
</style>
Все вышеперечисленное будет собрано воедино:
css
.a[data-v-f3f3eg9] .b {
/* ... */
}
Совет
DOM-контент, созданный с помощью v-html
, не подвержен влиянию скопированных стилей, но вы всё равно можете стилизовать его с помощью глубоких селекторов.
Селекторы slotted
По умолчанию стили с ограниченной областью действия не влияют на содержимое, отображаемое с помощью <slot/>
, поскольку считается, что они принадлежат родительскому компоненту, передающему их. Чтобы явно указать содержимое слота, используйте псевдокласс :slotted
:
vue
<style scoped>
:slotted(div) {
color: red;
}
</style>
Глобальные селекторы
Если вы хотите, чтобы только одно правило применялось глобально, вы можете использовать псевдокласс :global
вместо создания другого <style>
(см. ниже):
vue
<style scoped>
:global(.red) {
color: red;
}
</style>
Смешение локальных и глобальных стилей
Вы также можете включить в один и тот же компонент стили как с областью действия, так и без области действия:
vue
<style>
/* глобальные стили */
</style>
<style scoped>
/* локальные стили */
</style>
Советы по стилям с ограниченной областью действия
Стили с ограниченной областью действия не устраняют необходимость в классах. Из-за того, как браузеры отображают различные селекторы CSS,
p {color: red }
будет во много раз медленнее при ограничении области действия (т. е. в сочетании с селектором атрибутов). Если вместо этого вы используете классы или идентификаторы, например,.example {color: red }
, вы практически исключаете снижение производительности.Будьте осторожны с селекторами потомков в рекурсивных компонентах! Для правила CSS с селектором
.a .b
, если элемент, соответствующий.a
, содержит рекурсивный дочерний компонент, то все.b
в этом дочернем компоненте будут соответствовать правилу.
CSS-модули
Тег <style module>
компилируется как CSS-модули и предоставляет результирующие классы CSS компоненту в качестве объекта под ключом $style
:
vue
<template>
<p :class="$style.red">Это должно быть красным</p>
</template>
<style module>
.red {
color: red;
}
</style>
Полученные классы хэшируются, чтобы избежать столкновений, что позволяет добиться того же эффекта, что и при привязке CSS только к текущему компоненту.
Обратитесь к спецификации CSS-модулей для получения более подробной информации, такой как глобальные исключения и композиция.
Пользовательское имя инъекции
Можно настроить ключ свойства объекта инжектируемых классов, задав значение атрибуту module
:
vue
<template>
<p :class="classes.red">красный</p>
</template>
<style module="classes">
.red {
color: red;
}
</style>
Использование с Composition API
Доступ к инжектированным классам можно получить в setup()
и <script setup>
через API useCssModule
. Для блоков <style module>
с пользовательскими именами инъекций, useCssModule
принимает в качестве первого аргумента соответствующее значение атрибута module
:
js
import { useCssModule } from 'vue'
// внутри области видимости setup()...
// по умолчанию, возвращает классы для <style module>
useCssModule()
// возвращает классы для именованного модуля <style module="classes">
useCssModule('classes')
- Пример
vue
<script setup lang="ts">
import { useCssModule } from 'vue'
const classes = useCssModule()
</script>
<template>
<p :class="classes.red">red</p>
</template>
<style module>
.red {
color: red;
}
</style>
v-bind()
в CSS
Теги <style>
в однофайловых компонентах поддерживают привязку значений CSS к динамическому состоянию компонента с помощью CSS-функции v-bind
:
vue
<template>
<div class="text">привет</div>
</template>
<script>
export default {
data() {
return {
color: 'red'
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
Синтаксис работает с <script setup>
, а также поддерживает выражения JavaScript (должны быть заключены в кавычки):
vue
<script setup>
import { ref } from 'vue'
const theme = ref({
color: 'red'
})
</script>
<template>
<p>привет</p>
</template>
<style scoped>
p {
color: v-bind('theme.color');
}
</style>
Фактическое значение будет скомпилировано в хэшированное пользовательское свойство CSS, поэтому CSS остаётся статичным. Пользовательское свойство будет применяться к корневому элементу компонента с помощью встроенных стилей и реактивно обновляться при изменении исходного значения.