携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
scope,可以理解为作用域。
在Vue中,想必大家都知道用scoped来声明样式标签,在页面渲染完后各个页面的样式之间不会造成污染(即样式私有化,只能在当前组件中生效),为每一个Vue组件的style标签添加scoped,就是实现了样式的模块化。
代码如下:
<style scoped>
.text-info{
font-size:26px;
}
</style>
在浏览器中查看样式,可以看到这样的变化:
-
HTML中对应的的DOM节点添加一个data属性,就是代码中我们看到的的data-v-xxxx(data-v-hash),这会对这个元素进行唯一标识,data属性是一个唯一不重复的标记。
-
在样式的css选择器的末尾,增加了一个当前组件的data属性选择器来私有化样式
原理
本质上是使用 vue-loader 来实现的,具体步骤如下。
- vue-loader 解析vue组件,提取出 template、script、style 对应的代码块
- 构造组件实例,在组件实例的选项上绑定 ScopedId
- 对CSS 代码进行编译转化,应用 ScopedId 生成选择器的属性
所以,data-v-hash属性是一个唯一不重复的标记,通过解析 style 标签内容实现,同时通过 scopedPlugin 为每个选择器追加一个 [scopeId] 的属性选择器。
源码部分
- resourceQuery:根据引入文件的路径参数的匹配路径
- loader.pitch:调用 loader 上的 pitch 方法
- VueLoaderPlugin:用来注册公共的 pitcher,以及复制 webpack 的 rules
总结
- 当使用用scoped来声明样式标签的时候,PostCSS会给组件中的所有DOM添加一个唯一的动态属性
- 当使用
/deep/或::v-deep、>>>深度选择器进行样式穿透的时候,也会在css中加上[data-v-hash]来控制组件样式(在vue3.0环境下,使用/deep/编译时会报错) - 如果父子组件的选择器相同,子组件的样式会被父组件覆盖,原因是在生命周期中,
子组件相对于父组件会优先mounted