Skip to content
第 18 章 前端 ⏱ 12 分钟阅读

第 18 章:样式与 scoped ​

学习目标 ​

  • 区分 scoped 与全局 style
  • 用 :deep 穿透子组件
  • 用 CSS 变量做主题
  • 避坑:scoped 误作用域

一、scoped 基础 ​

vue
<template>
  <p class="text">Hello</p>
</template>

<style scoped>
.text { color: red; }
</style>

编译后:

html
<p class="text" data-v-abc123></p>
<style>.text[data-v-abc123] { color: red; }</style>

每个组件生成唯一 hash,样式只对当前组件生效。

⚠️ 坑 1:scoped 不会影响根元素的 id 选择器,容易出错。

二、:deep 穿透子组件 ​

vue
<style scoped>
.parent :deep(.child-class) {
  color: red;          /* 影响子组件的 .child-class */
}
</style>

Vue 3 写法::deep(.class),Vue 2 写法是 >>> .class 或 /deep/ .class。

三、:slotted 插槽内容 ​

vue
<style scoped>
:slotted(p) {
  color: blue;          /* 父组件传进来的 <p> */
}
</style>

四、:global 全局 ​

vue
<style scoped>
:global(.global-class) {
  color: red;
}
</style>

💡 三个 :xxx 对照::slotted() = 改父传进来的 slot 内容(父→子);:global() = 跳开 scoped 加属性(全项目生效);:deep() = 改子组件内部元素(子→子)。三个搭配用,Vue 3 scoped 样式基本就齐活。

五、CSS 变量主题 ​

vue
<!-- App.vue -->
<style>
:root {
  --primary: #42b883;
  --bg: #fff;
}
[data-theme="dark"] {
  --primary: #35495e;
  --bg: #1a1a1a;
}
</style>

💡 data-theme="dark" 加到 <html> 上(也常加 <body>,但推荐根元素):

加到哪效果推荐
<html data-theme="dark">全文档范围生效⭐⭐⭐ 最常用
<body data-theme="dark">也行,但 html 自身用的变量不变(滚动条/背景可能留白边)⭐⭐
<div id="app">只对 app 子树生效局部换主题
ts
// 推荐写到 <html>
document.documentElement.setAttribute('data-theme', 'dark')
vue
<template>
  <button class="btn">主色</button>
</template>

<style scoped>
.btn {
  background: var(--primary);
  color: #fff;
}
</style>

六、CSS Modules ​

vue
<template>
  <p :class="$style.text">CSS Modules</p>
</template>

<style module>
.text { color: red; }
</style>
ts
import { useCssModule } from 'vue'
const styles = useCssModule()
console.log(styles.text)   // 'text_abc123'

七、动态 class ​

vue
<script setup lang="ts">
const active = ref(false)
</script>

<template>
  <div :class="{ active, ['text-' + size]: true }" />
  <div :class="[isError ? 'red' : 'green']" />
</template>

八、UnoCSS / Tailwind ​

ts
// vite.config.ts
import UnoCSS from 'unocss/vite'
export default defineConfig({ plugins: [vue(), UnoCSS()] })
vue
<template>
  <button class="bg-blue-500 text-white px-4 py-2 rounded">按钮</button>
</template>

⚠️ 坑 2:UnoCSS 类名必须出现在源码中,不能动态拼接,否则扫描不到。

九、避坑清单 ​

坑解决
scoped 改不到子组件:deep
父组件想改第三方组件:deep
主题色切换CSS 变量
样式污染命名空间 + scoped

十、本章小结 ​

技术用途
scoped组件级样式隔离
:deep穿透子组件
:slotted插槽内容
:global局部全局
CSS Variables主题切换

动手练习 ​

  1. scoped 隔离:写两个组件,同名 class 互不影响
  2. :deep 穿透:改 Element Plus 按钮颜色
  3. 主题切换:用 CSS 变量实现 light / dark 切换

下一章:第 19 章:Vite + 工程化 →

本站基于 VitePress 构建 · 由 StackHub 团队维护