Vue style 属性 scoped 原理详解

Vue 样式属性 scoped 原理详解

讲讲 vue 中 scoped 属性的实现原理以及由此产生的特殊情况,然后引出样式的权重这一概念。

(一)什么是 scoped

当 style 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。通过该属性,可以使组件之间的样式互不污染,实现样式的模块化。

(二)scoped 原理

主要通过使用 PostCSS 来实现以下转换:

<style scoped>
	.example {
 		 color: red;
	}
</style>

<template>
  	<div class="example">hi</div>
</template>

转换结果:

<style>
	.example[data-v-7668812d] {
  		color: red;
	}
</style>

<template>
  	<div class="example" data-v-7668812d>hi</div>
</template>

通过给 dom 增加一个动态属性,然后 css 选择器也额外添加对应的属性来选择该 dom ,达到该样式只作用于含有该属性的 dom,实现组件样式的模块化。

(三)特殊用法

scoped 这个属性就是专门用于实现样式的模块化的,使用这个属性意味着样式不能经过外部或者全局的调整,在使用之初就应该规划好。

但有时候我们可能需要引入第三方组件,修改他的样式又不想去除 scoped 造成组件之间的样式污染,所以才有了下面的特殊用法。

scoped 穿透(深度作用选择器)

如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

<style scoped>
	.外层 >>> .第三方组件 { /* ... */ }
</style>

上述代码将会编译成:

.外层[data-v-7668812d] .第三方组件 { /* ... */ }

通过 >>> 可以使得在使用scoped属性的情况下,穿透scoped,修改其他组件的值。

实现原理其实就是加权重(后面细讲)

顺带一提,>>> 功能由 vue-loader 提供。 vue-loader 专门用于解析 vue 文件,提取每个语言块(html、script、style),如有必要会通过其它 loader 处理,最后将他们组装成一个 CommonJS 模块,module.exports 出一个 Vue.js 组件对象。

(四)权重选择器

CSS权重指的是样式的优先级,有两条或多条样式作用于一个元素,权重高的那条样式对元素起作用,权重相同的,后写的样式会覆盖前面写的样式。

权重等级

  1. !important,加在样式属性值后,权重值为 10000
  2. 内联样式,如:style=””,权重值为1000
  3. ID选择器,如:#content,权重值为100
  4. 类,伪类和属性选择器,如: .content、:hover、[data-v-7668812d] 权重值为10
  5. 标签选择器和伪元素选择器,如:div、p、:before 权重值为1
  6. 通用选择器(*)、子选择器(>)、相邻选择器(+)、同胞选择器(~)、权重值为0

相同权重下:内嵌样式 > 内部样式表 > 外联样式表

我们可以通过改变权重修改样式,scoped 实质就是添加了属性选择器增加了10的权重,我们只要超过他就可以了。

如 vue-loader 提供的 >>> 实质就是为第三方组件增加了外层属性的类,并且该类也带有属性选择器,相当于增加了20的权重。

那么我们可以为组件增加一个命名空间,防止变量污染,然后在当前命名空间下添加选择器增加权重达到修改样式的目的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章