文章目录
前言
在Vue组件中 style 标签中我们经常使用 scoped 属性来防止在修改父组件的样式时把其中的子组件中的样式修改掉,使得它的样式只在本组件中起作用,所有我们平常开发中都在 style 标签中添加这个属性。而如果在本组件想修改子组件中的样式,我们可以使用深度选择器来修改其子组件样式。
在开发中,经常遇到这个问题,于是想着一探究竟!
一、Vue中的Scoped深究
代码示例:<style lang="scss" scoped></style>
上面就是我们经常在Vue组件编写样式的代码
为什么我们经常在谷歌浏览器中检查元素时,看到有一些元素标签上面有类似<div class="demo" data-v-27e4e96e>
中含有data-v-xxx
的属性,这就是为了实现 scoped 效果而添加的这个属性。下面我们解释一下 scoped
属性实现的原理:
1.首先data-v-xxx
这个东西是通过文件路径名和内容 hash 生成的,每个Vue文件对应一个唯一的此 id
。
2.在 vueLoader
中,每当引入一个.vue
文件时,都会生成一个对应此文件的唯一id
。
3.那么在渲染出来的 HTML 标签中的data-v-xxx
属性是怎么添加上去的呢?我们知道,一个组件的render
方法返回的VNode
,描述了组件对应的 HTML 标签和结构,HTML 标签对应的 DOM 节点是从虚拟 DOM 节点构建的,一个 VNode
包含了渲染 DOM 节点需要的基本属性。其实在templateLoader
中,在每一个 DOM 标签对应的VNode
中添加了这个唯一的data-v-xxx
属性。
4.最后在stylePostLoader
中,如果style
标签中有scoped
属性,做的工作就是将所有选择器都添加一个属性选择器的组合限制,没有scoped
属性的话,就不会在选择器中多加入一个属性选择器。因为在style
标签中编写的选择器都添加了一个属性选择器[data-v-xxx]
,因为这个属性在本组件中的标签才存在,它的子组件或者其它组件是另外一个data-v-xxx
属性,所有这也就解释了为什么加了scoped
属性之后为什么修改其他组件的样式不会生效的原因,加了属性选择器之后就找不到组件外的元素了。
说明
提示:仅供互相学习,不保证完完全全正确!
本文参考文章:
下面是一个大佬分析的原理,有想从源码角度看的,可以看一下下面这篇文章:
从源码分析scoped原理