父组件改变子组件样式 深度选择器
我们不可避免会有覆盖第三方组件库 ( 如element-ui、Vuetify、view-design ) 样式的需求,整体的话好办,全局直接引入一个自定义的样式文件覆盖即可。如果只需在某个.vue
页面覆盖原样式,你会发现当该页面的 <style>
有 scoped
属性,直接修改样式,类似:.el-upload { width: 150px; }
是不起作用的。
虽然我们可以去掉scoped
,用嵌套自定义父级样式名的方式来解决。如下:
<style lang="sass">
.image-uploader {
/* 你的命名空间 */
width: 100%;
display: flex;
.el-upload {
/* element-ui 元素*/
width: 150px;
}
}
</style>
但因为会导致不必要的全局污染,这种做法并不推荐。
我们先来看下scoped
属性做了什么呢?它通过 PostCSS 给我们的代码做了一层转换处理,就是给自定义类名对应的标签加了一个属性(一个唯一标识符,格式类似data-v-6c53c59c
),然后给这个类名加上属性选择器,内容即是这个标识符。具体如下:
<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>
有scoped的情况,要在当前页面修改子组件的样式,可以通过 通过 >>>
来实现:
<style scoped>
.a >>> .b { /* ... */ }
</style>
但如果你使用了一些预处理插件(如 sass
), 你只能通过 /deep/
或 ::v-deep
来代替 >>>
实现想要的效果。亲测还是用::v-deep
比较保险,不然编译时可能会报错。
我是 vue-cli4 搭建的项目,css预处理是Sass/Scss (with dart-sass)
的配置,版本如下,供参考:
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
所以想只在某个页面覆盖 element-ui
的组件样式,你可以这样做:
.image-uploader::v-deep .el-upload-dragger {
width: 150px;
height: 150px;
}
效果如下: