
书接上文,此文章是在上文的基础上进行的
问题背景
在 Vue 项目中,默认情况下组件中的样式会全局生效,这很容易造成多个组件之间的样式冲突。例如,为一个组件的 h5 元素添加边框样式,可能会影响到其他组件中的 h5 元素。
解决方案:Scoped CSS
Vue 提供了 scoped 属性来解决样式冲突问题。当 <style> 标签带有 scoped 属性时,样式只作用于当前组件的元素。
工作原理
- 添加
scoped属性后,Vue 会自动为组件的每个元素添加一个唯一的data-v-xxx属性 - CSS 选择器会自动适配这些属性,实现样式隔离
- 样式只对当前组件及其子组件的根元素生效
修改后的组件代码
1. 父组件 (2.vue)
<template>
<div class="parent-container">
<h5>父组件</h5>
<div class="box">
<GlobalComponent />
<LocalComponent />
</div>
</div>
</template>
<script setup>
import LocalComponent from './LocalComponent.vue'
</script>
<style scoped>
.parent-container {
border: 2px solid blue;
padding: 10px;
margin: 10px;
}
.box {
display: flex;
gap: 10px;
}
</style>
修改说明:
- 添加
scoped属性实现样式隔离 - 父组件添加蓝色实线边框(2px)
- 添加内边距和外边距
2. 全局组件 (GlobalComponent.vue)
<template>
<div class="global-container">
<h5>全局组件</h5>
</div>
</template>
<style scoped>
.global-container {
border: 3px dashed purple;
height: 50px;
flex: 1;
background-color: yellow;
display: flex;
align-items: center;
justify-content: center;
}
</style>
修改说明:
- 添加
scoped属性实现样式隔离 - 边框改为 3px 紫色虚线
- 添加黄色背景色
- 使用 flex 布局居中内容
3. 局部组件 (LocalComponent.vue)
<template>
<div class="local-container">
<h5>局部组件</h5>
</div>
</template>
<style scoped>
.local-container {
border: 1px dashed black;
height: 50px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
</style>
修改说明:
- 添加
scoped属性实现样式隔离 - 使用 flex 布局居中内容
Scoped CSS 的特性
样式作用范围
- 父组件的 scoped 样式不会渗透到子组件内部
- 子组件的根元素会同时受父组件 scoped 样式和子组件 scoped 样式的影响
- 子组件内部元素只受子组件 scoped 样式的影响
深度选择器
如果需要在父组件中影响子组件的样式,可以使用深度选择器:
/* 使用 ::v-deep */
::v-deep .child-class {
/* 样式规则 */
}
/* 使用 /deep/ */
/deep/ .child-class {
/* 样式规则 */
}
/* 使用 :deep() */
:deep(.child-class) {
/* 样式规则 */
}
使用 CSS Modules
另一种解决方案是使用 CSS Modules:
<template>
<div :class="$style.container">
<h5 :class="$style.title">父组件</h5>
</div>
</template>
<style module>
.container {
border: 2px solid blue;
}
.title {
color: red;
}
</style>
组件样式对比
| 组件 | 边框样式 | 背景色 | 布局方式 |
|---|---|---|---|
| 父组件 | 2px 实线蓝色 | 默认 | flex 布局 |
| 全局组件 | 3px 虚线紫色 | 黄色 | flex 居中 |
| 局部组件 | 1px 虚线黑色 | 默认 | flex 居中 |
注意事项
- 避免过度使用 scoped:全局样式(如全局重置样式)不应使用 scoped
- 性能考虑:大量使用 scoped 会增加少量运行时开销
- 第三方库样式:引入第三方组件库时,可能需要使用深度选择器来覆盖样式
- 样式优先级:scoped 样式的优先级与普通样式相同,遵循 CSS 优先级规则
运行效果
页面显示:
- 父组件带有蓝色实线边框
- 全局组件带有紫色虚线边框和黄色背景
- 局部组件带有黑色虚线边框
- 三个组件的样式相互隔离,不会产生冲突