18.vue.js的scoped样式隔离?原理和使用?(1)
✅ 一句话理解:什么是 scoped
在 Vue 单文件组件 (.vue) 中使用 scoped,可以让这个组件的 CSS 只影响自己,不影响外部,也不被外部影响。
这段样式只会应用于当前组件的 .title,不会影响页面中其他 .title。
🧠 样式隔离的原理(重点)
Vue 实现样式隔离不是用 Shadow DOM,而是通过动态添加唯一的特定属性选择器,比如:
源码写的是:
Hello
Vue 编译后:
Hello
.title[data-v-123abc] {
color: red;
}
✔️ 所以只有组件内部元素带有 data-v-123abc 的才会命中样式。
❌ 外部写的 .title 样式不会影响这个组件,因为没有这个 data-*。
📦 这就叫做“基于 attribute 的 CSS 作用域”
Vue 在构建阶段(编译 SFC)时做了这几件事:
1. 给当前组件的每个 DOM 节点加一个唯一属性,比如 data-v-xxx
2. 修改你的 CSS 选择器,加上 [data-v-xxx] 作为作用域限定
3. 保证只有组件自己内部元素能被这些样式影响
✅ 怎么用 scoped
只要在
你也可以加上 <lang=“scss”> 或 <lang=“less”> 一起用:
⚠️ 注意事项
- 父组件样式不会影响子组件
✔️ 这个 div 样式不会传到 组件里面,因为它被作用域隔离了。
- scoped 样式无法作用于子组件内部结构
比如:
即使你写了:
.box p {
color: red;
}
如果这个
是在 组件内部的,样式是不会生效的,因为你的样式“进不去”子组件。
❗解决方式:要传入样式,子组件需要暴露结构、用 slot 或 props 控制。
- 使用 deep 穿透子组件内部样式
Vue 提供了穿透机制 ::v-deep:
/* 在 scoped 样式中修改子组件内部元素 */
:deep(.inner) {
color: red;
}
/* 或 Vue 3 的写法: */
::v-deep(.inner) {
color: red;
}
这会忽略作用域限制,强制作用于子组件内部。
✅ 如果不加 scoped 会怎么样?
• 所有样式是全局的,类似写在 的
🎯 什么时候加 scoped?
场景 建议
组件要完全封装 ✅ 加 scoped
公共组件(按钮、卡片) ✅ scoped(除非用 CSS Modules)
需要覆盖子组件样式 ❌ scoped + ::v-deep 或干脆不 scoped
页面级组件 可加可不加(看全局需求)
🧠 进阶拓展:其他隔离方式
方法 原理 是否推荐
scoped 编译阶段自动添加属性 ✅ 推荐
CSS Modules 使用类名哈希化 ✅ 更彻底但配置多
Shadow DOM(Web Components) 通过原生 DOM 隔离 ❌ Vue 默认不支持,不推荐普通项目用
✅ 总结
问题 解释
scoped 是什么? 让样式只作用于当前组件的 CSS 隔离方式
原理是什么? 编译时给 DOM 加唯一 data-* 属性,并修改 CSS 选择器
怎么用?