你真的了解scoped吗

704 阅读2分钟

摄图网_400480547_鲸鱼与少年(非企业商用).jpg

一、scoped

1.1 什么是scoped

scoped 属性是 HTML5 中的新属性,是一个布尔属性。

1.2 scoped作用

对于style标签上添加scoped属性的vue组件,为了避免样式的污染,做了如下处理

  1. 给当前组件的所有标签添加一个不重复的data属性(形如:data-v-40b76154)来表示唯一性

  2. 为了避免影响全局样式

  • 给每句CSS选择器末尾(编译后生成的CSS语句)加一个当前组件的data-v-hash属性选择器来私有化样式
  1. 为了避免影响子组件的样式
  • 只会给子组件的最外层标签上添加当前组件的data-v-hash属性

⬆️上述效果主要是通过PostCss转译实现的,下面来看一下转译前后代码对比⬇️

//转译前
<template>
  <div class="wrap">
     <div class="example">你真的了解scoped吗?</div>
  </div>
</template>

<style scoped>
.wrap .example{
    color: red;
}
</style>
//转译后
<template>
   <div class="wrap" data-v-109a2208>
      <div class="example" data-v-109a2208>你真的了解scoped吗?</div>
   </div>
</template>

.wrap .example[data-v-109a2208]{
    color: red;
}

所以,如果组件的style标签上有scoped,那么在当前组件的style标签上写的样式就无法作用到子组件上了

我们可以使用下面的方法来解决这个问题⬇️

二、解决方式

2.1 两个Style

2.1.1 使用方式

全局样式可以作用到当前组件的子组件上

<style>
  /* 全局样式 */
</style>

<style scoped>
  /* 局部样式 */
</style>

2.1.2 效果展示

<template>
    <el-breadcrumb separator="/">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item :to="{ path: '/' }">活动管理</el-breadcrumb-item>
    </el-breadcrumb>
</template>

<script>
export default {
  name: "deep",
};
</script>

<style>
.el-breadcrumb__item:nth-child(1) .el-breadcrumb__inner.is-link {
  color: red;
}
.el-breadcrumb__item:nth-child(2) .el-breadcrumb__inner.is-link{
  color: blue;
}
</style>

image.png

<template>
    <el-breadcrumb separator="/">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item :to="{ path: '/' }">活动管理</el-breadcrumb-item>
    </el-breadcrumb>
</template>

<script>
export default {
  name: "deep",
};
</script>

<style>
.el-breadcrumb__item:nth-child(1) .el-breadcrumb__inner.is-link {
  color: red;
}
</style>

<style scoped>
.el-breadcrumb__item:nth-child(2) .el-breadcrumb__inner.is-link{
  color: blue;
}
</style>

image.png

2.2 穿透

2.2.1 三种深度作用选择器

>>>

介绍:如果是css原生样式,那么可以直接使用 >>>

问题:但如果是scss/sass/less的话可能无法识别

<style lang="css" scoped>
    .a >>> .b{
        XXX
    }
</style>

/deep/

介绍:less/sass的样式穿透

问题:vue-cli3编译时,deep方式会报错或者警告

<style lang="css" scoped>
    .a {
        /deep/ .b {}
    }
</style>

::v-deep

介绍:推荐用这种方式

<style lang="css" scoped>
    .a {
        ::v-deep .b {}
    }
</style>

2.2.2 穿透的实现原理

没加穿透

<style scoped>
    .wrap .example {
        color: red;
    }
</style>

.wrap .example[data-v-469af010] {
  color: red;
}

添加穿透

<style scoped>
    .wrap ::v-deep .example {
        color: red;
    }
</style>

.wrap[data-v-469af010] .example {
  color: red;
}

由此可知,穿透只是改变了data-v-hash的位置

2.2.3 效果展示

此处用element-ui的el-breadcrumb组件(面包屑导航)来验证上面讲的内容

没加穿透

<template>
    <el-breadcrumb separator="/">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
        <el-breadcrumb-item>活动列表</el-breadcrumb-item>
        <el-breadcrumb-item>活动详情</el-breadcrumb-item>
    </el-breadcrumb>
</template>

<script>
export default {
  name: "deep",
};
</script>

<style scoped>
.el-breadcrumb__item .el-breadcrumb__inner.is-link {
  color: red;
}
</style>

image.png

添加穿透

<template>
    <el-breadcrumb separator="/">
        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
        <el-breadcrumb-item>活动列表</el-breadcrumb-item>
        <el-breadcrumb-item>活动详情</el-breadcrumb-item>
    </el-breadcrumb>
</template>

<script>
export default {
  name: "deep",
};
</script>

<style scoped>
.el-breadcrumb__item ::v-deep .el-breadcrumb__inner.is-link {
  color: red;
}
</style>

image.png

三、参考

segmentfault.com/a/119000002…

cloud.tencent.com/developer/a…