主要是用于修改很多vue常用的组件库(element, vant, AntDesigin),虽然配好了样式但是还是需要更改其他的样式,就需要用到样式穿透。
scoped的原理
vue中的scoped 通过在DOM结构以及css样式上加唯一不重复的标记:data-v-hash的方式,以保证唯一(而这个工作是由过PostCSS转译实现的),达到样式私有化模块化的目的。
总结一下scoped三条渲染规则
1.给HTML的DOM节点加一个不重复data属性(形如:data-v-123)来表示他的唯一性。
2.在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-123])来私有化样式。
3.如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性。
PostCSS会给一个组件中的所有dom添加了一个独一无二的动态属性data-v-xxxx,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom, 从而达到了'样式模块化'的效果。
使用elementUi来做一个例子
在vue组件中引入一个el-input标签,然后给它添加相应的样式,看一下页面上的变化
vue组件代码:
<template>
<div>
<el-input v-model="input" placeholder="Please input" class="username"/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const input = ref('')
</script>
<style scoped>
.username{
width: 200px;
height: 50px;
}
</style>
在页面上渲染后的结果:可以明显看到class后面加上了属性选择器
我们试着通过el-input__inner给输入框内部的input元素改变一下背景颜色:
发现页面上并没有生效:追究原因,原来是在el-input__inner上也添加了属性选择器,这就是scope属性引起的scope特征第二条和第三条冲突了,所以.el-input__inner[data-v-7a7a37b1]找不到对应的元素
解决scoped样式穿透
第一种解决办法
最简单的解决办法就是去掉scoped属性:
这样就生效了:但是这可能就会引起样式冲突,导致其他页面上的组件样式也会改变
第二种解决办法
使用样式穿透,在vue2中可以使用/deep/ .el-input__inner 这种方式,在vue3中需要使用:deep(.el-input__inner)这种方式:
这样修改之后,真正的样式选择器就会改变为:所以就能成功选择到对应的标签