vue scoped踩坑记录

1,376 阅读2分钟

样式修改失败】前几天开发需求,遇到一个坑,我无论怎么修改样式都无法完成 对公司内部的一个基础组件样式进行修改。经过排查,因为我在style标签上加入了scoped属性,于是我需要对scoped这个属性进行研究。

scoped作用

让.vue中的样式不影响其他.vue组件中的样式。

在vue组件中,为了使样式私有化(模块化),不对全局造成污染,在style标签上添加scoped属性,以表示它只属于当下的模块。

如图所示,我添加了scoped属性,dom和 css选择器后面都会添加一个不重复的data属性,如图中的:data-v-f29e1056。

所以,scoped属性会做以下两件事:

  • 给HTML的DOM节点增加一个不重复的data属性。
  • 在每句css选择器的末尾(编译后生成的css语句)加一个当前组件的data属性选择器,对样式进行私有化。

于是我们会遇到两种情况:

  • 在不使用scoped的组件中加入了使用了scoped的组件。
  • 在使用了scoped属性的组件中加入了使用了scoped的组件。

在 不使用 scoped的组件中引用带scoped属性的组件

<template>
 <div class="son-warp">
  <son class="son">text</son>
 </div>
</template>
...
<style scoped>
 .son-warp{
  display:inline-block;
 }
 .son{
  padding: 5px 10px;
  font-size: 12px;
  border-raduis: 2px;
 }
</style>

//father.vue
<template>
 <div class="father">
  <p class="title"></p>
   
  <son></son>
 </div>
</template>
...
<style>
 .father{
  width: 200px;
  margin: 0 auto;
 }
 .father .son{
  border-raduis: 5px;
 }
</style>

最后的结果会是:

<div class="father">
 <p class="title"></p>
 <!-- son上面定义的组件 -->
 <div data-v-f29e1056 class="son-warp">
  <son data-v-f29e1056 class="son">text</son>
 </div>
</div>
/*son.vue渲染出来的css*/
.son-warp[data-v-f29e1056]{
 display:inline-block;
}
.son[data-v-f29e1056]{
 padding: 5px 10px;
 font-size: 12px;
 border-radus: 2px;
}
/*father.vue渲染出来的css*/
.father{
 width: 200px;
 margin: 0 auto;
}
.father.son{
 border-raduis: 5px;
}

此时由于权重关系,我们只需要调整对应的权重就可以调出我们需要的样式。

在 使用 scoped的组件中引用带scoped属性的组件

在父组件的style标签加入scoped属性

//father.vue
<template>
 <div class="father">
  <p class="title"></p>
   
  <son></son>
 </div>
</template>
...
<style scoped>
 .father{
  width: 200px;
  margin: 0 auto;
 }
 .father .son{
  border-raduis: 5px;
 }
</style>

浏览器渲染的结果是:

<div data-v-57bc25a0 class="father">
 <p data-v-57bc25a0 class="title"></p>
 <!-- son是上面定义的组件 -->
 <div data-v-57bc25a0 data-v-f29e1056 class="son-warp">
  <son data-v-f29e1056 class="son">text</son>
 </div>
</div>
/*son.vue渲染出来的css*/
.son-warp[data-v-f29e1056]{
 display:inline-block;
}
.son[data-v-f29e1056]{
 padding: 5px 10px;
 font-size: 12px;
 border-radus: 2px;
}
/*father.vue渲染出来的css*/
.father[data-v-57bc25a0]{
 width: 200px;
 margin: 0 auto;
}
.father .son[data-v-57bc25a0]{
 border-raduis: 5px;
}

于是我们可以发现一个问题就是.father .son末尾的标记是father的标记,找不到对应的dom节点,于是我们设置样式就失效了。

解决方法

  1. 引入样式
  2. 再写一个不加scoped的style(最好同时用BEM css命名规范 等方式去限定style影响范围)