style scoped 原理

6 篇文章 0 订阅
4 篇文章 0 订阅

在了解 <style scoped></style> 前先回顾vue实例的挂载和渲染流程:

其中template模板在运行时进行编译,它会利用Vue内部的编译器进行模板的编译,字符串模板会转换为抽象的语法树,即AST树(抽象语法树)

一、vue-loader 

       一个 vue 的项目中,整个项目是通过 .vue 单文件组件组织的,我们写的单文件组件都被处理为了SFC对象(单个文件组件), 即包含了单个HTML模块, 单个脚本模块, 一个或多个样式模块的功能完备的结构单元。

       vue-loader 的存在我们才得以组件化的形式进行编码,使vue 组件里的 style、template、script分别会编译为相应的 style 标签、html 标签以及 script 标签引入。

下面是一个简单的 vue 组件例子:

<template>
  <div class="App">
    {{ msg }}
    <ParentA></ParentA>
    <ParentB></ParentB>
  </div>
</template>
<style>
.App {
  color: #000;
}
</style>


// --- ParentA
<template>
  <div class="ParentA">
    {{ msg }}
  </div>
</template>
<style>
.ParentA {
  color: red;
}
</style>


// --- ParentB
<template>
  <div class="ParentA">{{ msg }}</div>
</template>
<style>
.ParentB {
  color: blue;
}
</style>

它通过 vue-loader 进行编译后,在浏览器中是这样显示的:

<head>
  <style type="text/css">
	.ParentA {
	  color: red;
	}
  </style>
</head>

<body>
  <div class="ParentA"> ParentA </div>
  <div class="ParentA">ParentB</div>
</body>

可以看出 ParentA.vue 组件对.ParentA 类的样式更改是会污染到全局样式的,也就是说会影响到 ParentB.vue 组件样式,一个项目中,不同的人的开发会导致两个不同的组件中使用了相同的类名,从而互相之间产生影响,vue-loader 给我们提供了 scoped 属性,从编码上解决了这个问题。

给 ParentA.vue 的 style 标签添加上 scoped 属性,这时候编译输出的是:

<style type="text/css">
  .ParentA[data-v-183fa219] {
	color: red;
  }
</style>
<div data-v-183fa219  class="ParentA"> ParentA</div>
<div class="ParentA">ParentB</div>

可以看到输出的 ParentA.vuestyle 标签内多了一个属性选择器,并且 html 标签上也多了对应的 data-v-183fa219 属性值。这样的话,无论 .ParentA 的样式怎么变都不会影响到 ParentB 的样式了,即使它们使用了同一个类名,这就是所谓的作用域约束

二、scoped 原理

  1. 编译过程中Webpack通过调用Vue Loader,单文件组件都被处理为了SFC对象
  2. 判断当前SFC对象样式块中是否有scoped属性
  3. 有的话,给组件HTML模板添加自定义属性 (Attribute) data-v-x, 以及给组件内CSS选择器添加对应的属性选择器 (Attribute Selector) [data-v-x], 达到组件内样式只能生效与组件内HTML的效果, 代码效果如下:
     
    <style>
    .example[data-v-f3f3eg9] {
      color: red;
    }
    </style>
    
    <template>
      <div class="example" data-v-f3f3eg9>hi</div>
    </template>
  4. 补充3: stylePostLoader 在对样式模板进行解析过程中,对含 scoped 标记的模板引入插件 stylePlugins/scoped.js, scoped.js 将[data-v-x], 添加到选择器末尾,所以有scoped 的style模版编译后,会携带一个[data-v-x]属性选择器,只对对应的html模板生效,即起到了‘使样式变得私有’的作用
  5. 另外,在第四步的过程中,如果出现深度作用选择器,那么就不会将[data-v-x],添加到选择器末尾,所以可以用深度选择器来覆盖带有scoped的组件的样式:

参考:

深入剖析Vue源码 - 完整挂载流程和模板编译

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值