Scoped定义
在Vue中,scoped属性通过PostCSS插件来实现样式的局部作用域。当你在一个Vue组件的<style>标签中使用scoped属性时,这个插件会自动给组件模板中的每个元素添加一个独一无二的属性(通常是一个带有哈希值的data-v-*属性)。同时,它还会转换相应的CSS选择器,使它们包含这个独一无二的属性。
scoped原理
通过给组件中DOM元素和CSS各自都添加一个相同且唯一的属性选择器,让当前的CSS文件的样式只对当前组件生效。
scoped过程
-
扫描模板:PostCSS插件首先会扫描Vue组件的模板,收集所有的元素和组件。
-
添加唯一属性:为每个元素生成一个唯一的属性(如
data-v-f3f3eg9),并在模板渲染时将这些属性添加到对应的DOM元素上。 -
转换CSS选择器:然后,插件会遍历组件的CSS样式,将每个选择器转换为包含这个唯一属性的形式。例如,一个原本的选择器
.my-class会被转换为.my-class[data-v-f3f3eg9]。 -
应用转换后的样式:最终,转换后的CSS样式被应用到组件的DOM元素上,确保了样式的局部作用域。
scoped属性的作用优点:
样式隔离
使用scoped可以确保组件的样式不会与其他组件的样式发生冲突。即使两个组件使用了相同的类名或选择器,由于样式作用域的隔离,它们的样式也不会相互干扰。
组件化开发
在组件化开发中,每个组件都应该有自己独立的样式。通过scoped,你可以为每个组件编写独立的CSS样式,使得组件更加模块化和可重用。
维护性
使用scoped可以提高样式的可维护性。由于样式只应用于当前组件,因此在修改或调试样式时,你可以更加专注于当前组件的样式,而无需担心对其他组件的影响。
scoped样式的缺点:
-
样式权重增加: Scoped 样式会给每个样式增加特定的选择器属性,导致了样式的权重增加。这可能会导致样式覆盖和继承方面的问题,需要更高的权重来覆盖 Scoped 样式。
-
无法直接操作子组件样式: Scoped 样式限制了父组件对子组件样式的直接操作。如果需要修改子组件内部的样式,就需要使用深度作用选择器或其他特殊方式来解决。
-
性能问题: 使用 Scoped 样式时,浏览器需要额外处理样式选择器,可能会对性能产生一定影响。尤其是当使用标签选择器时,性能下降更为显著。
CSS Modules[推荐使用]
CSS Modules,在 <style> 上增加 module 属性,即<style module> 。
<style module> 代码块会被编译为 CSS Modules 并且将生成的 CSS 类作为 $style 对象的键暴露给组件,可以直接在模板中使用 $style。而对于如 <style module="content"> 具名 CSS Modules,编译后生成的 CSS 类作为 content 对象的键暴露给组件,即module 属性值什么,就暴露什么对象。
useCssModule模块名使用
<script setup lang="ts">
import { useCssModule } from 'vue'
// 不传递参数,获取<style module>代码块编译后的css类对象
const style = useCssModule()
console.log(style.success) // 获取到的是success类名经过 hash 计算后的类名
// 传递参数content,获取<style module="content">代码块编译后的css类对象
const contentStyle = useCssModule('content')
</script>
<template>
<div class="success">普通style red</div>
<div :class="$style.success">默认CssModule pink</div>
<div :class="style.success">默认CssModule pink</div>
<div :class="contentStyle.success">具名CssModule blue</div>
<div :class="content.success">具名CssModule blue</div>
</template>
<!-- 普通style -->
<style>
.success {
color: red;
}
</style>
<!-- 无值的css module -->
<style module lang="less">
.success {
color: pink;
}
</style>
<!-- 具名的css module -->
<style module="content" lang="less">
.success {
color: blue;
}
</style>