- **scoped: **仅影响当前组件下所有DOM节点、子组件根节点;
- 非scoped: 影响整个页面下所有DOM节点;(即会影响页面内其他组件下的DOM节点);
- 组件内隔离方案: style声明为
module
,且在HTML节点上使用:class="[$style.class1, .., $style.classN]";
- 为避免受父组件样式影响,创建组件叶,应使用
空样式div
包含有效DOM元素;
1 scoped原理
场景:需要修改当前组件,或子组件根节点的样式,同时不影响页面内其他组件样式
- vue给所有声明scoped
组件的根节点
,生成一个全局唯一的data属性(格式:data-v-[hash]
); - 该组件的data属性会被添加至组件内所有的DOM节点(包含
子组件的根节点
); - 在scoped内的css选择器末尾(编译后的css),添加一个当前组件data属性选择器;
2 深度选择器:deep()
场景:修改子组件样式,同时不影响页面内其他使用该子组件的样式
方法:scoped + :deep()
<template>
<div class="root">
<el-input />
</div>
</template>
<style lang="scss" scoped>
.root {
.el-input__inner {
/* 编译结果:.root .el-input__inner[data-v-xxxx] 样式无效 */
background-color: pink;
}
:deep(.el-input__inner) {
/* 编译结果:.root[data-v-xxxx] .el-input__inner 样式生效 */
background-color: red;
}
}
</style>
3 插槽样式:slotted()
场景:在子组件内,定义slot样式
- 父组件
<template>
<ComponentA>
<span class="red">插槽内容(红色,由:slotted()定义)</span>
</ComponentA>
</template>
<script setup lang="ts">
import ComponentA from './ComponentA.vue';
</script>
- 子组件
<template>
<slot />
<span class="red">子组件内容(默认颜色,不受影响)</span>
</template>
<style lang="scss" scoped>
:slotted(.red) {
color: red;
}
</style>
- 效果
4 全局样式:global()
场景:定义全局样式
<style lang="scss" scoped>
:global(div) {
color: red;
}
/* 等价于 */
div {
color: red;
}
</style>
5 动态css(v-bind)
场景:绑定js变量
<script setup lang="ts">
import { ref } from 'vue';
const colorRed = ref('red');
const color = ref({
red: 'red',
green: 'green',
});
</script>
<style lang="scss" scoped>
.demo {
color: v-bind(colorRed);
background: v-bind('color.green'); // 对象要加 ''
}
</style>
6 CSS隔离 module
场景:CSS样式仅限组件内有效
方法:style声明为module,并且在DOM节点使用
:class="$style.root"
或:class="[$style.root, $style.demo]"
<template>
<div :class="[$style.root, $style.demo]">
仅组件内有效,不影响页面内其他class="demo"组件的样式
</div>
</template>
<style lang="scss" module>
.root {
background-color: gray;
}
.demo {
color: red;
}
</style>