Skip to content

组件基础

组件化开发是Vue3的核心特性之一,它允许你将UI拆分为独立、可复用的组件。本章节将详细介绍Vue3中组件的定义、注册和使用方法。

什么是组件?

组件是Vue3中可复用的UI单元,它可以包含模板、脚本和样式。组件可以被多次使用,提高代码的复用性和可维护性。

组件的定义

在Vue3中,我们可以使用两种方式定义组件:

1. 单文件组件(.vue文件)

单文件组件是Vue3中最常用的组件定义方式,它将模板、脚本和样式放在同一个文件中:

vue
<template>
  <div class="hello">
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const title = ref('Hello Vue3!')
const message = ref('Welcome to Vue3 component')
</script>

<style scoped>
.hello {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

h1 {
  color: #42b983;
}
</style>

2. 组合式API定义组件

在Vue3的组合式API中,我们可以使用 defineComponent 函数来定义组件:

javascript
import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const title = ref('Hello Vue3!')
    const message = ref('Welcome to Vue3 component')
    
    return {
      title,
      message
    }
  }
})

组件的注册

在Vue3中,组件可以通过两种方式注册:

1. 全局注册

全局注册的组件可以在整个应用中使用:

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

const app = createApp(App)

// 全局注册组件
app.component('HelloWorld', HelloWorld)

app.mount('#app')

2. 局部注册

局部注册的组件只能在注册它的组件中使用:

vue
<template>
  <div>
    <HelloWorld />
  </div>
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

组件的使用

1. 基本使用

在模板中,你可以像使用HTML标签一样使用组件:

vue
<template>
  <div>
    <HelloWorld />
  </div>
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

2. 传递属性

你可以通过props向组件传递数据:

vue
<!-- ParentComponent.vue -->
<template>
  <div>
    <HelloWorld title="Hello Vue3!" message="Welcome to Vue3 component" />
  </div>
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<!-- HelloWorld.vue -->
<template>
  <div class="hello">
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script setup>
defineProps({
  title: String,
  message: String
})
</script>

3. 事件处理

组件可以通过emit向父组件传递事件:

vue
<!-- ParentComponent.vue -->
<template>
  <div>
    <HelloWorld @click="handleClick" />
  </div>
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'

const handleClick = () => {
  console.log('Button clicked')
}
</script>

<!-- HelloWorld.vue -->
<template>
  <div class="hello">
    <button @click="emit('click')">Click me</button>
  </div>
</template>

<script setup>
const emit = defineEmits(['click'])
</script>

组件的生命周期

Vue3的组合式API提供了一系列生命周期钩子函数:

1. 常用生命周期钩子

  • onMounted:组件挂载后执行
  • onUpdated:组件更新后执行
  • onUnmounted:组件卸载后执行
  • onBeforeMount:组件挂载前执行
  • onBeforeUpdate:组件更新前执行
  • onBeforeUnmount:组件卸载前执行

2. 使用生命周期钩子

vue
<template>
  <div class="hello">
    <h1>{{ title }}</h1>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const title = ref('Hello Vue3!')

onMounted(() => {
  console.log('Component mounted')
})

onUnmounted(() => {
  console.log('Component unmounted')
})
</script>

组件的命名

1. 组件名的规范

  • PascalCase:推荐使用大驼峰命名法,如 HelloWorld
  • kebab-case:在模板中使用时,应转换为短横线分隔的形式,如 <hello-world />

2. 单文件组件的命名

单文件组件的文件名应该与组件名保持一致,使用PascalCase命名法,如 HelloWorld.vue

组件的最佳实践

1. 组件的职责单一

每个组件应该只负责一个特定的功能,保持组件的职责单一:

vue
<!-- 好的做法:职责单一的组件 -->
<template>
  <button class="btn" :class="{ 'btn-primary': isPrimary }">
    {{ text }}
  </button>
</template>

<script setup>
defineProps({
  text: String,
  isPrimary: Boolean
})
</script>

<!-- 不好的做法:职责过多的组件 -->
<template>
  <div>
    <button @click="handleClick">{{ buttonText }}</button>
    <input v-model="inputValue" type="text">
    <p>{{ message }}</p>
  </div>
</template>

2. 组件的通信

组件之间的通信应该清晰、明确:

  • 父传子:使用props
  • 子传父:使用emit
  • 跨组件通信:使用provide/inject或状态管理

3. 组件的复用

组件应该设计为可复用的:

  • 使用props和emit使组件更加灵活
  • 避免硬编码值
  • 提供合理的默认值

4. 组件的性能

注意组件的性能:

  • 合理使用 v-ifv-show
  • 避免在模板中使用复杂表达式
  • 使用 defineAsyncComponent 实现异步组件

组件的使用场景

1. 通用组件

通用组件是可以在多个地方使用的基础组件,如按钮、输入框、卡片等:

vue
<template>
  <button class="btn" :class="{ 
    'btn-primary': type === 'primary',
    'btn-secondary': type === 'secondary'
  }">
    {{ text }}
  </button>
</template>

<script setup>
defineProps({
  text: {
    type: String,
    default: 'Button'
  },
  type: {
    type: String,
    default: 'primary'
  }
})
</script>

<style scoped>
.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.btn-primary {
  background-color: #42b983;
  color: white;
}

.btn-secondary {
  background-color: #ccc;
  color: black;
}
</style>

2. 页面组件

页面组件是应用中的各个页面,如首页、详情页、列表页等:

vue
<template>
  <div class="home">
    <h1>Home Page</h1>
    <p>Welcome to the home page</p>
    <Button text="Click me" />
  </div>
</template>

<script setup>
import Button from './components/Button.vue'
</script>

3. 布局组件

布局组件用于组织页面的整体结构,如头部、导航、侧边栏、页脚等:

vue
<template>
  <div class="layout">
    <header class="header">Header</header>
    <nav class="nav">Nav</nav>
    <main class="main">
      <slot></slot>
    </main>
    <footer class="footer">Footer</footer>
  </div>
</template>

<style scoped>
.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header {
  background-color: #333;
  color: white;
  padding: 10px;
}

.nav {
  background-color: #f0f0f0;
  padding: 10px;
}

.main {
  flex: 1;
  padding: 20px;
}

.footer {
  background-color: #333;
  color: white;
  padding: 10px;
  text-align: center;
}
</style>

总结

组件化开发是Vue3的核心特性之一,它允许你将UI拆分为独立、可复用的组件。通过组件化开发,你可以提高代码的复用性和可维护性,使应用的结构更加清晰。

在使用组件时,你应该遵循组件的命名规范,保持组件的职责单一,合理设计组件的通信方式,以及注意组件的性能。

在后续的章节中,我们将学习Vue3的组件通信,包括props、emit、provide/inject等内容。

© 2026 编程马·菜鸟教程 版权所有