scoped的本质是通过给组件内元素添加唯一属性(如data-v-xxx)并重写css选择器为.classname[data-v-xxx],实现样式仅作用于当前组件;但无法隔离全局选择器,且动态内容和第三方组件插槽需额外穿透处理。

Vue 单文件组件(SFC)由 <template></template>、<script></script> 和 <style></style> 三部分构成,样式默认全局生效,加 scoped 属性后才实现局部作用域。
基本结构:三个标签各司其职
每个 .vue 文件必须且只能包含一个 <template></template>、一个 <script></script> 和一个 <style></style> 块(自定义块如 <docs></docs> 可选,但非标准核心)。
-
<template></template>:定义组件的 HTML 结构,必须有且仅有一个根元素(如<div> 或 <code><section></section>) -
<script></script>:导出组件配置对象(Vue 2)或使用<script setup></script>(Vue 3),负责数据、方法、生命周期等逻辑 -
<style></style>:写 CSS/SCSS/Less 等样式,默认影响全局;加scoped后仅作用于当前组件 DOM - 普通选择器(如
.btn)会自动转成.btn[data-v-f3f3eg9] - 子组件的根元素也会带上该属性,但其内部元素不会——所以父组件的 scoped 样式无法直接穿透到子组件内部
- 若需影响子组件深层节点,可用
:deep(.child-class)(Vue 3)或>>>(Vue 2)进行深度选择 - 动态生成的内容(如
v-html插入的 HTML)不会被自动加上 scope 属性,需手动处理或改用 CSS Modules - 第三方 UI 组件(如 Element Plus)的插槽内容属于子组件,父组件 scoped 样式默认无效,需配合
:deep()或::v-deep - 想让某条样式全局生效,可在同一
<style></style>块中并存 scoped 和非 scoped:<style></style>写全局规则,<style scoped></style>写局部规则 - 组件级样式优先用
<style scoped></style> - 跨组件共享的视觉规范,用
<style></style>+ CSS 变量或预处理器@import - 需要穿透样式的场景,明确使用
:deep()并注释原因,避免滥用
样式作用域:scoped 是如何工作的?
添加 scoped 属性后,Vue 会在编译时为组件内所有元素自动添加唯一属性(如 data-v-f3f3eg9),同时将 CSS 选择器重写为带该属性的形式,从而实现样式隔离。
常见样式作用域误区与应对
scoped 并不等于“完全隔绝”,实际使用中容易忽略边界情况:
推荐实践:平衡可维护性与灵活性
多数场景下应默认启用 scoped,避免样式污染;对需要复用的通用样式(如工具类、主题色变量),建议提取到独立的 variables.css 或使用 CSS 自定义属性(CSS Custom Properties)。











