1、scoped
scoped
属性用于限制样式仅应用于当前组件。- 当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染。
原理:当样式中加了scoped属性时候,编译的时候会自动给每一个dom节点都添加一个不重复的自定义属性,例如:data-v-4cd6f8b2(在同一个组件中,添加在所有节点上这个属性是一样的)
style标签拥有scoped属性编译后
通过代码可以看到加了scoped之后btnbg后面多了一个属性[data-v-4cd6f8b2]
2、样式穿透
- 下面三种样式穿透的方法均不是标准css的一部分,而是vue的特殊语法
- >>>、/deep/与::v-deep在实现效果上来说是一样的。它们都是Vue中用于穿透组件scoped样式隔离的语法,允许组件内的样式影响到子组件或更深层次的DOM元素
(1)>>>(适用于css原生样式)
如果项目使用的是css原生样式而没有用 scss 、sass、less ,那么可以直接使用 >>>
穿透修改
(2)/deep/ 与 ::v-deep
项目中如果用到了预处理器 scss 、sass、less 操作符 ,那么用>>> 可能会因为无法编译而报错 ,比如在 <style lang="scss" scoped>,可以使用 /deep/或者::v-deep穿透
- 在Vue 2.x项目中,/deep/和
>>>
被广泛使用来实现样式的穿透。 - 在Vue 3.x项目中,推荐使用
::v-deep
来实现样式的穿透,因为它提供了更好的语义清晰度和兼容性
3、代码演示样式穿透
(1)暂且叫下面的组件为a组件,a组件中有一个testView组件
<template><div class="test_bg"><testView></testView></div>
</template><style lang="scss" scoped>.test_bg{padding: 50px;background-color: #FAB32D;.test_app{background-color: rebeccapurple;width: 100%;height: 200px;.test_app_c{background-color: red;width: 100%;height: 100px;.test_app_c_a{background-color: green;width: 100%;height: 20px;}}}
}
</style>
(2)下面是testView组件,下面我们叫做b组件吧
<template><div class="test_app"><div class="test_app_c"><div class="test_app_c_a"></div></div></div>
</template><script setup>
</script><style lang="scss" scoped>
.test_app {background-color: rebeccapurple;width: 50%;height: 200px;.test_app_c {background-color: red;width: 50%;height: 100px;.test_app_c_a {background-color: green;width: 50%;height: 20px;}}
}
</style>
上面代码style中用了scoped属性,父子组件相互隔离,样式彼此不受影响,运行代码如下图
其中外面黄色部分是a组件中的标签,紫色是b中的标签,按理说两个组件相互隔离,那么紫色部分应该渲染的是b组件里的样式,withd:50%,但是我们发现他其实是渲染a组件中的width:100%,后面子元素的样式才是渲染的b组件的样式,这里要注意,查看编译后的样式就能明白,a组件中添加了data-v-4cd6f8b2属性,b组件中隔离后往元素添加了data-v-5dd7fed2属性,test_app这个div同时添加了a和b组件的属性,样式被a组件的样式覆盖了
重点来了,这个时候如果我们想要样式穿透,在a组件中修改b组件中子元素的样式,那我们可以用/deep/ 或者 ::v-deep 来去掉每个元素中添加的属性,修改a组件中的样式代码后如下
.test_bg{padding: 50px;background-color: #FAB32D;::v-deep .test_app{background-color: rebeccapurple;width: 100%;height: 200px;.test_app_c{background-color: red;width: 100%;height: 100px;.test_app_c_a{background-color: green;width: 100%;height: 20px;}}}
}
我们只是在.test_app前面加上了::v-deep,这个时候test_app后面所有的子元素就穿透了scoped的约束,实际上加上了::v-deep就是去掉约束data-v-4cd6f8b2以及data-v-5dd7fed2
下面对比看一下没加::v-deep与加上的区别
没加
加上后
从图可以看出,添加了::v-deep后test_app_c_a后面就去掉了[data-v-5dd7fed2],代码运行结果如下
大家可以通过代码以及运行效果图来对比,然后完全掌握约束的原理以及样式穿透的原理。