使用 vue 的同学一定不会陌生 scoped。如果在 <style/>
标签中设置 scoped 属性,则它的样式只应用到当前组件的元素中。意味着想直接覆盖子组件的样式是不行的,但是可以使用特殊的方法实现。
举一个实际的例子, element 带状态表格。其状态的控制其实就是根据传入的函数,筛选出需要加状态的行,返回 className。然后再给该 className 自定义样式。但是示例代码的 style 是这样子写的:
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
并没有加 scoped 属性在 <style/>
,全局样式当然能够生效。问题是我想使用局部样式,只想在当前组件中应用这个状态。
PostCSS
设置 scoped 属性后,通过 PostCSS 转换代码:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
装换结果为:
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
html 标签会自动加类似 data-v-f3f3eg9
这样的属性,css 也会用 .example[data-v-f3f3eg9]
的方式转换。
子组件根元素
如果想使用 .example .child { }
去覆盖子组件中的样式,并不会生效。使用 scoped 后,父组件的样式不会渗透到子组件中。但是子组件的根节点会受影响,这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
深度作用选择器
如果想让类似 .example .child { }
样式生效,可以使用 >>> 操作符。有些 css 预处理器无法解析 >>> 操作符,可以使用 /deep/ 代替。例如:
<style scoped>
.example >>> .child { /* ... */ }
</style>
编译为:
.example[data-v-f3f3eg9] .child { /* ... */ }
网友评论