文章目录
若文章有任何纰漏或未涉及你想了解的内容,欢迎在评论提出,我会尽最快速度回复。
什么是scoped style
html scoped
scoped style最初是一个html5的特性。使用该属性,即为样式添加了作用域,使样式仅应用到 style 元素的父元素及其子元素上。
但仅有firefox支持,它的定义与使用详见html scoped。
这种scoped特性之所以没有被广泛使用,是因为其将样式写在html内部,很影响代码可读性和可维护性。在传统的面向页面开发时代,样式作用域的迫切性也并不是很高。
vue scoped
与html scoped类似的,vue引入了scoped style的概念。
它的作用是将声明样式的作用域限制于当前组件与子组件的根节点。它的实现方法是为html节点添加唯一序列标识,即使用特性选择器进行样式定义。
例:
<style scoped>
.target{
color : royalblue
}
</style>
将被处理为
<style>
.target[data-v-7ba5bd90]{
color : royalblue
}
</style>
为什么使用scoped style
MVVM框架的主要场景是面向组件的单页面应用开发(SPA)。
在SPA开发中,所有组件的CSS都会被打包挂载到单一页面(原理),因此尽管开发是组件化的,但CSS最终是混在一起的,组件间样式会相互污染。
- 为避免样式污染,我们有两种解决方法,而scoped style是其中一种,它的本质是CSS模块化。另一种是使用传统的class/id分类。
- 像面向页面开发一样,使用唯一的class/id进行细粒度区分,除全局样式外,不使用元素选择器。
- 使用scoped style使样式组件化。
- 两者的优劣:
class与scoped style各有优劣,class分类简单原始,但在大项目开发中,容易出现标签冗余,就像bootstrap,可读性很差。而scoped style可以避免标签冗余,实现样式的组件化,但其性能稍逊,且遇到修改第三方UI库的场景时,需要使用深度选择器。
scoped style 详解
理解误区
很多初学者将scoped style理解为使组件不受全局样式的污染。
但这个理解方向反了,实际情况是:
- scoped style是将样式限定于本组件,不污染其它组件。
- 全局样式依然可能影响scoped style
- 全局选择器的优先级低于同类型特性选择器,即scoped style。
示例:
- son组件:
<div>
<span>{{msg}}</span>
</div>
<style scoped>
span {
color: royalblue; /* 特性选择器优先级高,生效 */
}
</style>
<style>
span {
color: red; /* 优先级低,被覆盖 */
border: solid; /* 全局样式有效 */
}
</style>
- app组件
<div id="app">
<span>app here</span>
<son></son>
</div>
全局样式污染了app组件,而scoped style则不会影响。
作用域与深度选择器
scoped style为当前元素以及其子元素的根节点添加统一的序列标识。
如下所示:
style scoped的目的就是为了实现样式组件化,我们只会对本组件元素进行样式定义,没有理由对子组件内部元素跨级修改样式,这是与组件化初衷矛盾的。
但引入第三方UI库后,又要修改默认样式时,我们不得不深入子元素修改内部样式。
如果使用后代选择器是没法修改子元素内部样式的。
示例如下:
<style scoped>
.el-input .el-input__inner {
border: royalblue solid;
}
</style>
等价于
<style>
.el-input .el-input__inner[data-v-469af010] {
border: royalblue solid;
}
</style>
子元素的内部元素并没有序列标识,故无法被选中。
此时,我们需要使用深度选择器 >>> (在sass/scss中写作/deep/),这样就可以深入子元素内部修改样式了。
<style scoped>
.el-input >>> .el-input__inner {
border: royalblue solid;
}
</style>
优先级
在相同级别的选择器下,特性选择器即scoped style的优先级高于全局样式。
而优先级更高的选择器仍会高于低优先级的特性选择器,比如id选择器优先于类特性选择器。
示例如下:
- 同级别选择器下, scoped style定义的border样式生效
<style scoped>
.el-input >>>.el-input__inner {
border: royalblue solid;
}
</style>
<style>
.el-input__inner {
border: brown solid;
}
</style>
- 优先级更高的id选择器定义的border样式生效
<style scoped>
.el-input >>>.el-input__inner {
border: royalblue solid;
}
</style>
<style>
#ipt{
border: orange solid;
}
</style>
scoped style与class的性能对比
scoped style的性能要稍劣于class。
性能差别测试如下:
- class选择器渲染效率:
- scoped style(特性选择器)
动态生成内容
动态生成内容,即v-html因为渲染机制,会不受scoped样式影响,但你仍可以通过深度选择器设置它们的样式