组件基础
本教程共 40 篇 · 第 11 篇 · 更新于 2026-07-29 · 约 8 分钟阅读
11. 组件基础
本节目标:学会定义和使用组件,理解组件树,掌握 Props 和自定义事件的基本用法。
什么是组件
组件把 UI 拆成独立、可复用的块。一个应用通常组织成嵌套的组件树:
App (根组件)
├─ TodoList
│ └─ TodoItem
│ ├─ DeleteButton
│ └─ EditButton
└─ TodoFooter
├─ ClearButton
└─ Statistics
和嵌套 HTML 元素类似,但 Vue 组件封装了自定义内容和逻辑。
定义组件
用构建工具时,通常用 .vue 单文件组件:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">你点了 {{ count }} 次</button>
</template>
不用构建工具时,组件就是一个包含 Vue 选项的 JavaScript 对象:
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return { count }
},
template: `
<button @click="count++">
你点了 {{ count }} 次
</button>
`
}
使用组件
在父组件里导入子组件。假设计数器组件在 ButtonCounter.vue:
<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>
<template>
<h1>子组件在这里!</h1>
<ButtonCounter />
</template>
用 <script setup> 时,导入的组件自动暴露给模板。
Note不用
<script setup>时,需要用components选项手动注册。
组件可以无限复用:
<ButtonCounter />
<ButtonCounter />
<ButtonCounter />
每次使用组件都会创建新的实例,各自维护独立的状态。
TipSFC 里推荐用 PascalCase 标签名(
<ButtonCounter />),和原生 HTML 区分。在 DOM 模板里要用 kebab-case(<button-counter>)。
Props —— 向组件传数据
组件需要接收外部数据才能有用。Props 是注册在组件上的自定义属性:
<!-- BlogPost.vue -->
<script setup>
defineProps(['title'])
</script>
<template>
<h4>{{ title }}</h4>
</template>
defineProps 是编译时宏,不需要导入。声明后的 props 自动暴露给模板。
传值:
<BlogPost title="我的 Vue 之旅" />
<BlogPost title="用 Vue 写博客" />
用 v-bind 传动态值:
<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
/>
Tip关于 Props 的完整用法(验证、类型、默认值),后面有专门章节。
组件事件 —— 子组件向父组件通信
子组件需要”向上”通信时,用自定义事件系统。
父组件用 @ 监听子组件事件:
<BlogPost @enlarge-text="postFontSize += 0.1" />
子组件用 $emit 触发事件:
<!-- BlogPost.vue -->
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">放大文字</button>
</div>
</template>
也能声明式地列出组件会触发的事件:
<script setup>
defineProps(['title'])
defineEmits(['enlarge-text'])
</script>
defineEmits 返回 emit 函数,可以在 <script setup> 里用:
const emit = defineEmits(['enlarge-text'])
emit('enlarge-text')
插槽 —— 向组件传内容
有时候需要这样用组件:
<AlertBox>
出错了!
</AlertBox>
用 <slot> 占位:
<!-- AlertBox.vue -->
<template>
<div class="alert-box">
<strong>这是错误提示</strong>
<slot />
</div>
</template>
<slot> 是内容插入的位置。关于插槽的更多用法后面会详细讲。
动态组件
用 <component :is> 可以动态切换组件:
<component :is="currentTab"></component>
:is 的值可以是已注册组件的名字字符串,或者导入的组件对象。
切换时组件会被销毁重建。用 <KeepAlive> 可以保持不活跃组件的状态。
本节回顾
- 组件是独立可复用的 UI 块
- 用
<script setup>定义组件最方便 - Props 向组件传数据,
defineProps声明 - 组件事件让子组件向父组件通信,
$emit触发 <slot>插槽向组件插入内容<component :is>动态切换组件