Vue中样式覆盖-style的scoped属性
背景
项目使用Vue和ElementUi,想要覆盖ElementUi默认的输入框样式,新增自定义CSS样式,根据el-input编译后生成的class修改,但是样式并不生效。
后来发现修改1
<style type="text/css" scoped></style>
标签里的scoped删除就生效了。
原因
scope可以做到样式私有化,及当前样式只作用于当前模块,不会影响全局。
通过查看DOM结构发现:vue通过在DOM结构以及css样式上加唯一不重复的标记,以保证唯一,达到样式私有化模块化的目的。具体的渲染结果是怎样的,通过一个例子来说明。
举个栗子
一个公共组件button,为了样式模块化,给其加上scoped属性
1 | //button.vue |
浏览器渲染的button组件,其html和css结构如下:
1 | <div data-v-2311c06a class="button-warp"> |
1 | .button-warp[data-v-2311c06a]{ |
从上面的案例可以看出,添加了scoped属性的组件,为了达到组件样式模块化,做了两个处理:
- 给
HTML
的DOM
节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性 - 在每句
css
选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式
但这势必影响到css的优先级,scoped虽然达到了组件样式模块化,但是会导致每个样式的权重加重
。理论上我们要修改这个样式的话,需要更高的权重去修改,增加了复杂度。
外部引用
栗子说明了单个组件渲染,当遇到组件相互调用,如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性。
解决方案
vue-loader的深度作用选择器。
在vue.js中,<style scoped>
的作用域在本html
页面,<style>
样式的作用域则是全局(即所有html页面),由于我把其中一个html页面的<style scoped>
scoped去掉,这个页面的样式就变成了全局样式,当其它页面和这些全局样式重class
名时,样式会被覆盖(vue默认全局样式覆盖局部样式),这样就导致当前页面定义样式影响到全局样式。
如何在<style scoped>
局部样式中覆盖全局样式:父组件cssName+ /deep/+第三方库需要更改的cssName
1 | 比如修改class为el-input__inner的元素, |