vue | scoped与深度选择器

本文介绍了Vue中的scoped style特性,用于限制样式只作用于当前组件及其子组件,防止样式污染。讨论了scoped style的工作原理,澄清了理解误区,并探讨了如何在需要时使用深度选择器。此外,还比较了scoped style与class的性能和优先级问题。


若文章有任何纰漏或未涉及你想了解的内容,欢迎在评论提出,我会尽最快速度回复。

什么是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分类。
  1. 像面向页面开发一样,使用唯一的class/id进行细粒度区分,除全局样式外,不使用元素选择器。
  2. 使用scoped style使样式组件化。
  • 两者的优劣:
    class与scoped style各有优劣,class分类简单原始,但在大项目开发中,容易出现标签冗余,就像bootstrap,可读性很差。而scoped style可以避免标签冗余,实现样式的组件化,但其性能稍逊,且遇到修改第三方UI库的场景时,需要使用深度选择器。

scoped style 详解

理解误区

很多初学者将scoped style理解为使组件不受全局样式的污染。
但这个理解方向反了,实际情况是:

  1. scoped style是将样式限定于本组件,不污染其它组件
  2. 全局样式依然可能影响scoped style
  3. 全局选择器的优先级低于同类型特性选择器,即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选择器优先于类特性选择器。
示例如下:

  1. 同级别选择器下, scoped style定义的border样式生效
<style scoped>
.el-input >>>.el-input__inner {
  border: royalblue solid;
}
</style>

<style>
.el-input__inner {
  border: brown solid;
}

</style>

在这里插入图片描述

  1. 优先级更高的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样式影响,但你仍可以通过深度选择器设置它们的样式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值