1、什么是scoped
vue组件中,在style标签中有一个属性,叫做scoped。
当此标签拥有scoped属性的时候,该组件下的css样式只适用于本组件,而不会影响全局组件。这其实也相当于样式的模块化了。
2、scoped实现的原理
其实scoped中最重要的就是PostCSS,PostCSS是一种css的编译的工具。来看一下转译之前的代码:
编译前的代码:
<template>
<span class="textScoped">scoped测试</span>
</template>
<script>
</script>
<style scoped>
.textScoped{
color: red;
}
</style>
编译之后的代码:
<template>
<span data-v-3e5b2a80 class="textScoped">scoped测试</span>
</template>
<script>
</script>
<style scoped>
.textScoped[data-v-3e5b2a80]{
color: red;
}
</style>
总结一下scoped三条渲染规则
- 给HTML的DOM节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性
- 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式
- 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性-
编译后,我们发现css中,PostCSS给所有的dom都添加了一个独一无二的动态属性,给css选择器也添加了一个对应的属性选择器,这样就可以让样式只作用于该属性的dom元素(组件内部的dom)。
3、Vue scoped (>>> || /deep/ )穿透
参考: Vue scoped (>>> || /deep/ )穿透
使用 scoped 后,父组件的样式将不会渗透到子组件中。
1)父组件添加了scoped,子组件无论加不加scoped,父组件不能通过子组件的样式选择器修改子组件样式;
2)父组件不添加scoped,子组件添加scoped,父组件是可以通过子组件样式选择器来修改子组件的样式;
Vue引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除 scoped 属性造成组件之间的样式污染。此时只能通过 >>>,穿透 scoped。
有些Sass 之类的预处理器无法正确解析 >>>。可以使用 /deep/ 操作符 ( >>> 的别名)
vue组件中,在style设置为scoped的时候,里面在写样式对子组件是不生效的,如果想让某些样式对所以子组件都生效,可以使用 /deep/ 深度选择器。
参考:Vue scoped CSS 与深度作用选择器 /deep/
使用 scoped 后,父组件的样式将不会渗透到子组件中。例如(无效):
<template>
<div id="app">
<el-input class="text-box" v-model="text"></el-input>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
text: 'hello'
};
}
};
</script>
<style lang="less" scoped>
.text-box {
input {
width: 166px;
text-align: center;
}
}
</style>
解决方法:
使用深度作用选择器 /deep/ , 加上/deep/ 然后修改子组件的内部标签样式 ,注意要写出正确的选择器
<template>
<div id="app">
<el-input v-model="text" class="text-box"></el-input>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
text: 'hello'
};
}
};
</script>
<style lang="less" scoped>
.text-box {
/deep/ input {
width: 166px;
text-align: center;
}
}
</style>