Возможности 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, не подвержено влиянию стилей c ограниченной областью действия, но его все же можно стилизовать с помощью глубоких селекторов.
Селекторы слотов
По умолчанию стили с ограниченной областью действия не влияют на содержимое, отображаемое с помощью <slot/>, так как считается, что оно принадлежит родительскому компоненту, который его передаёт. Чтобы явно указать на содержимое слота, используйте псевдокласс :slotted:
vue
<style scoped>
:slotted(div) {
color: red;
}
</style>Глобальные селекторы
Если необходимо, чтобы одно правило применялось глобально, можно использовать псевдокласс :global, а не создавать еще одну секцию <style> (см. ниже):
vue
<style scoped>
:global(.red) {
color: red;
}
</style>Сочетание локальных и глобальных стилей
В одном компоненте можно вместе использовать как scoped, так и обычные секции 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">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')- Example
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 остаётся статичным. Пользовательское свойство будет применяться к корневому элементу компонента с помощью inline-стилей и реактивно обновляться при изменении исходного значения.