vue scoped原理 和 样式穿透

1,161 阅读1分钟

scoped作用

scoped是将该组件的css样式表只作用于组件自身,不影响父组件和子组件的样式。

scoped的实现原理

解释不太清,就不写详细了,随便记一下给自己看。

<style scoped>标签加上scoped属性,会执行两个步骤。

1.给html标签加上data-v-hash属性

image.png

2.给css选择器加上[data-v-hash]属性选择器

image.png

这样避免了多个组件之间css样式的混合。

原理非常简单,但是在实验过程中也发现了一些意外。

问题一:scoped会给哪些html标签加上data-v-hash属性呢?

答:会给两类标签加上该属性。类型一:该组件中除子组件外的所有html标签。类型二:当子组件只有一个根元素时,会给子组件的根元素加上该属性。

image.png

当子组件没有唯一的根元素时,子组件标签不会添加父元素的data-v-hash属性;当子组件有唯一的根元素时,只有根元素同时挂载父组件和自身组件的data-v-hash属性,根元素内部的标签不会挂载父组件的data-v-hash属性,这也是保证父子组件css样式不会混淆的原因。

在vue2中规定,一个组件中只能有一个根元素,这就导致每个子组件的根元素上都同时挂载父组件和自身的data-v-hash属性。

问题二:scoped会完全把父子组件的样式分割吗?

答:不能,问题一中已经发现当子组件只有一个根元素时会挂载父元素的data-v-hash属性。若根标签为<div>,若父组件中对div添加了样式,那么父组件对div的样式就会影响到子组件的根标签<div>,所以父子组件的样式没有完全分割开。

问题三:父组件对子组件的根标签添加样式,和子组件自己给根标签添加样式,谁的优先级高?

答:选择器权值相同时,父组件样式的优先级高。

下图div为子组件的根标签 image.png

子组件选择器权重高时,子组件优先级高。 image.png

发现四:当<script>标签中不写样式的时候就不会给该组件的html标签添加data-v-hash属性,有注释也会挂载。

样式穿透

项目中使用很多ui组件,但有的样式需要我们加以修改。

方法一:::v-deep 选择器{}

分情况:

如果要修改ui组件的根组件样式,可以直接修改不用加::v-deep,因为父组件的样式可以对子组件的根元素产生影响;如果要修改ui组件跟标签内部标签的样式需要加上::v-deep;

原理是:::v-deep,取消了该选择器中的属性选择器,就能匹配到子组件的内部标签了。

有时配合!import使用。

<style lang="less" scoped>
.el-select {
    border: solid 5px yellow;
    ::v-deep .select-trigger{
        border: solid 10px yellowgreen;
    }
}
</style>

image.png

方法二: 新开拓一个<style>标签

在原有<style scoped>标签旁边先开拓一个<style>标签。这样新的style标签没有scoped的限制,作用域可以贯穿子组件内部,但是会影响到其他的无关组件,使用有风险,尝试需谨慎。