scoped作用原理及样式穿透的应用

5 篇文章 0 订阅
3 篇文章 0 订阅

(1)scoped作用原理

scoped是Vue样式作用域的一个特性,相信很多人经常在项目中用它来避免样式污染(即样式隔离)。当我们在一个组件中给style标签加上scoped时候,它会遵循以下三个规则,如下

  • 为组件实例生成一个唯一标识(可以称为文件指纹),给当前组件中的每个标签加一个标签属性(如data-v-66976dba,当前组件中的标签属性都一样,但与其它所有组件中的标签属性都不一样);
  • 在scoped中的每个选择器的最后一个元素后(加在最后一个元素后)添加一个属性选择器,如过原选择器为.container #school div,则更改后的选择器为.container #school div[data-v-xxxx];
  • 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性‌(这一规则确保了样式作用域的局部性,避免了样式的全局扩散)。

(2)对第三条的详细解释

前两条规则很容易理解,第三条我要着重说一下。如下,我写了两个组件,一个父组件parent.vue和一个子组件son.vue,界面如下:

在这里插入图片描述

其中两个组件我都用了scoped,我们可以打开控制台看看元素。

在这里插入图片描述

根据红色和紫色下划线应该能看出问题,这恰恰印证了第三条规则。其实不难看出child-area(子组件的根元素)作为一个桥梁它是有两个文件指纹属性的,但它内部的所有标签不会继承祖先组件中的文件指纹属性。(图中data-v-226932b2是子组件自己的自定义属性,如果我没在子组件中写scoped,那自然是不存在data-v-226932b2的)。

(3)场景----微调第三方库样式

我们把上面每个组件的唯一标识符称为文件指纹(相信这一点很好理解)。由上面三条规则我们知道文件指纹都是放在选择器末尾的,但恰恰有些时候,我们需要把文件指纹位置移动到非末尾。我举个例子,在做项目时候经常会用到第三方库如element-ui等,有时候我想微调某些组件在某个页面的样式,直接在style(不含scoped)中修改组件样式显然是不行的,因为在实际开发中可能有多人进行模块化开发,这样子极易造成样式污染覆盖。如下:

在这里插入图片描述

我们想修改第三方组件input的宽度,直接在scoped中对el-input__inner操作是无效的。因为这相当于

  .el-input__inner[data-v-e43c18bc]{
    width: 200px;
  }

这明显不会生效,毕竟el-input组件是没有这个文件指纹的,那应该怎么解决呢?如果我们有办法自己控制文件指纹的位置,那就一切就迎刃而解了。这时候样式穿透就可以完美解决这个问题。

(4)样式穿透

如下,我用样式穿透写法更正代码:

  /deep/.el-input__inner{
    width: 200px;
  }

可以看看界面,如下:
在这里插入图片描述
界面生效,我们可以看看控制台元素中style标签内容:

在这里插入图片描述

这就很好理解了,使用了样式穿透可以改变文件指纹的位置,我们可以把样式穿透理解成一种占位符。

(5)补充

或许还有些朋友在开发中喜欢用以下方法解决上述问题:在需要操作的组件文件中加一个style标签不带scoped,然后在内部写第三方组件的选择器,并且在该选择器前面写一个具有该父组件标识的选择器来进行样式限制,以防止样式污染。
如下:

<style>
 .test-area .el-input__inner{
  width: 200px;
 }
</style>

如上.test-area为父组件的根标签选择器。以上做法也是可以的,但不太好,我们必须确保整个项目中所有文件中的根元素命名要唯一,不然就有出现样式污染的可能性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值