首页 / Vue3 入门教程 / 组件基础

Vue3 入门教程

组件基础

本教程共 40 篇 · 第 11 篇 · 更新于 2026-07-29 · 约 8 分钟阅读

VueVue3 入门教程组件Props事件插槽

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 />

每次使用组件都会创建新的实例,各自维护独立的状态。

Tip

SFC 里推荐用 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> 动态切换组件