详解源码vue3的样式穿透scope
scope底层实现
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属性选择器追加到谁后面
使用样式穿透后可以写的更优雅一点
现在我们来看看他的源码
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规范,如果符合,则帮我们做样式穿透,实现的方式其实就是挪动下属性选择器的追加位置,第三个框框就是挪动的实现
观察这里的挪动
更多推荐
所有评论(0)