vue3在打包之后只有一个html文件,为了避免样式污染可以为style标签引入scope属性,它的原理十分简单,它会为每一个dom元素都添加一个data属性,这个属性是不重复的,然后会在当前组件的选择器的末尾,追加一个属性选择器,当两者匹配上时,会把样式命中到dom上

scope渲染规则:

1.每个dom元素会自带一层data

2.当前组件的选择器会追加一个属性选择器来保证一一对应

3.当一个组件引入另一个组件时,scope的唯一data属性只会添加到最外层标签

此时,我们就在backstage这个单文件组件里引入elementplus的组件,我们观察一下此时data属性的位置 

发现只有最外层的div有data属性 

现在我们有一个需求,把边框的白线给去掉 

打开调试工具可知我们需要选中截图红框的元素并修改其css属性

 如果我们做出如下修改

 

发现页面并没有变化,原因就在于container这个容器是由一层data的,此时的属性选择器是被加到了el-table_cell后面,我们并没有命中到container,所以样式不生效

做出如下修改

 我们再观察此时页面的情况

 发现此时的属性选择器被追加到了container后,此时我们就成功命中父级元素container,后面操作它的子元素样式就可以顺利生效。所以这个:deep()深度选择器就干了一件事情,deep写在谁后面,就会把data属性选择器追加到谁后面

使用样式穿透后可以写的更优雅一点

 

现在我们来看看他的源码

vue3源码在此

scope的具体实现在compiler-src里,这个文件主要就是用于处理后缀名.vue的单文件组件的,

这里写了三个解析器分别解析template标签、script标签、style标签

 这里观察到会首先判断是否开启scope属性,如果有,则会往postcss plugin 里添加一个插件,

我们点进去看看这个插件具体做了什么事情

 发现这个插件主要是将css转化成AST,有点类似babel,babel主要操作就是将高阶es6语法先转义成AST,得到这么一个树之后我们就可以随意操作它的节点,甚至做一些定制化的操作

我们点进processRule

它首先先声明了一个弱集合processeRules,然后判断rule是否存在,这里的rule是AST,如果有,就return出去,如果没有就往里面添加AST

然后会遍历这个AST,为每个item都调了rewirteSelector 这个函数

我们再看看这个函数

首先判断我们所使用的深度选择器,如果是vue2的这两种,就不给我们做样式穿透并弹出警告,我们接着往下看

 首先还是会判断类型,类型pseudo如下

 然后再判断我们的深度选择器是否符合vue3规范,如果符合,则帮我们做样式穿透,实现的方式其实就是挪动下属性选择器的追加位置,第三个框框就是挪动的实现

 观察这里的挪动

 

Logo

前往低代码交流专区

更多推荐