大白话理解scoped

在style标签设置scoped属性,可以使组件之间的样式不互相污染,达到样式私有模块化的目的。

接下来,我们分别从原理、优缺点、解法来认识下

原理:

style标签设置scoped属性,经过PostCSS转译后,在DOM结构以及css样式上加唯一的标记:data-v-hash属性,意味着CSS样式就只能作用于当前组件,从而使得组件之间的样式不互相污染,达到样式私有模块化的目的。 

1)当前组件的DOM根节点及其子节加一个不重复data属性(如data-v-19fca230),

2)当前组件引入子组件,那么,给子组件的根节点加上当前组件的data属性

3)在每句css选择器的末尾加一个当前组件的data属性选择器(如data-v-19fca230)

举个例子

例一:

<template>
  <div class="wrap">
    <h1 class="parent1"> hello </h1>
    <h1 class="parent2"> hi </h1>
</div>
</template>
<style scoped>
    .wrap{
        backgorund: lightsalmon
     .parent1{
       color: red
     } }
.parent2{
   color: green
 }
</style> 

转译后, 当前组件的Dom根节点及子节点都有了一个[data-v-5406a40e]属性,其选择器末尾加一个当前组件的[data-v-5406a40e]属性

   

例二:引入子组件

// 父组件
<template> <div class="wrap"> <h1 class="parent">当前组件1</h1> <childCompontent class="childCompontent"></childCompontent>   </div> </template> <style scoped> .childCompontent{ backgorund: lightgreen } </style>
// 子组件
<template>
    <div>
    <h1 class="child-wrap">子组件</h1>
  </div>
</template>
<style scoped>
  .child-wrap{
    color: lightpink
  }
</style>  

转译后,

当前组件引入子组件,在子组件的style标签加了scoped,  那么,仅子组件的Dom根节点会带有父组件相同的[data-v-5406a40e]属性。

带有childCompontent的标签,其选择器末尾加一个当前父组件的[data-v-5406a40e]属性,而引入的child-wrap的标签,其选择器末尾加一个当前组件,也就是子组件组件的[data-v-180cce0f]属性

  

要是想在当前父组件中修改子组件的样式,怎么办呢? 

直接修改,如下

// 父组件
<template> <div class="wrap"> <childCompontent class="childCompontent"></childCompontent>   </div> </template> <style scoped>
.wrap .child-wrap{
color: red
}
</style>

结果,没有生效。那是因为渲染后,css选择器样式如下:

// 父组件渲染后
.wrap .child-wrap[data-v-5406a40e] { color: red; }
// 子组件渲染后
.child-wrap[data-v-180cce0f] { 
  color: lightpink;
}

目标子组件css选择器是.child-wrap[data-v-180cce0f] ,而我们在父组件修改的是data-v-5406a40属性的child-wrap,根本作用不到我们想要的DOM节点上,

这种情况我们在父组件内部写的任何样式都不会影响到子组件组件,所以这就尴尬了。。。。

解决方法:

1)在模板中使用两次style标签:一个用于私有样式(带scoped属性),一个用于共有样式

<style lang="scss">
    /* 需要覆盖的样式--注意css权重 */
 
.wrap .childCompontent .child-wrap{
    color: red
  }
</style>
<style lang="scss" scoped>
    /* 当前组件的私有样式 */
</style>

2)使用 >>> 或者 /deep/ 操作符  (Sass、Less等预处理器无法正确解析 >>>,可以使用/deep/ )

<style lang="scss" scoped>
.wrap /deep/ .child-wrap {
    color: red 
  }
}
</style>

参考Vue loader官方文档 

posted @ 2019-11-17 20:29  灰姑娘的冰眸  阅读(641)  评论(0编辑  收藏  举报