Skip to content
On this page

什么是组件?

组件是 Vue 的核心概念。把页面拆成一个个独立、可复用的小块,每个小块就是一个组件。

页面 = 拼积木
┌──────────────────────────────┐
│  Header(顶部导航组件)        │
├──────────────────────────────┤
│  Main(主要内容区组件)        │
├──────────────────────────────┤
│  Footer(底部组件)            │
└──────────────────────────────┘

每个组件就是一个 .vue 文件,封装了 HTML、JavaScript 和 CSS。

单文件组件(SFC)的结构

vue
<template>
  <!-- 这个组件的 HTML -->
</template>
<script>
// 这个组件的 JavaScript 逻辑
</script>
<style scoped>
/* 这个组件的 CSS 样式 */
</style>

组件嵌套关系

Vue 应用本质上是一棵组件树——一个组件里放另一个组件,层层嵌套。

App.vue(根组件)
├── Header.vue(顶部导航)
├── Main.vue(主内容区)
│   ├── Article.vue(文章卡片)
│   └── Article.vue(文章卡片...复用多次)
└── Footer.vue(底部)

父组件写法

vue
<template>
  <div class="layout">
    <Header />
    <Main />
    <Aside />
  </div>
</template>
<script>
import Header from './components/Header.vue'
import Main from './components/Main.vue'
import Aside from './components/Aside.vue'
export default {
  components: { Header, Main, Aside }
}
</script>

三个步骤import 导入 → components 注册 → <template> 中使用。

数据流向:从上到下

数据从父组件流向子组件,从根往叶子流。父组件通过 props 把数据传给子组件,子组件不能直接改父组件的数据——这是 Vue 的核心设计原则。


组件注册方式

局部注册(推荐)

只在当前组件内可用:

vue
<template>
  <MyButton />
</template>
<script>
import MyButton from './MyButton.vue'
export default {
  components: { MyButton }
}
</script>

优点:依赖关系清晰,支持 tree-shaking,好维护。

全局注册

main.js 中注册,整个应用任何地方都能用:

javascript
import { createApp } from 'vue'
import App from './App.vue'
import MyButton from './components/MyButton.vue'

const app = createApp(App)
app.component('MyButton', MyButton)
app.mount('#app')

缺点main.js 会越来越臃肿,无法 tree-shaking。

场景用哪种
通用组件(按钮、弹窗...到处用)全局注册
特定页面的组件局部注册
不确定是否会复用先局部,需要时再提升

💡 Tip:先用局部注册,等这个组件确实在 3 个以上地方被引用了,再考虑全局注册。


<slot> — 预留的"内容洞"

组件里的 <slot> 就像是一个"占位符":

vue
<!-- MyCard.vue -->
<template>
  <div class="card">
    <slot></slot>               <!-- 默认插槽 -->
    <slot name="footer"></slot> <!-- 具名插槽 -->
  </div>
</template>
vue
<!-- 使用时 -->
<MyCard>
  <p>这是卡片的内容</p>
  <template v-slot:footer>
    <button>查看详情</button>
  </template>
</MyCard>

scoped — 组件样式隔离

vue
<style scoped>
.title { color: red; }    /* 只影响本组件内的 .title */
</style>

不加 scoped = 全局样式 = 影响整个应用。开发时默认加 scoped 是个好习惯。

组件命名规范

  • 多个单词MyButton 而不是 Button(避免冲突)
  • PascalCase:MyButtonUserProfile
  • 模板中 <MyButton /><my-button></my-button> 都行