Vue3的defineComponent是定义组件的核心方法,支持选项式API和组合式API两种写法,提供完善的TypeScript类型推断。
主要特性包括:
- 支持props、emits的类型定义;
- 可与自定义Hooks结合使用;
- 提供泛型组件支持;
- 在<script setup>语法糖中自动推断类型。
相比Vue2,defineComponent为组件开发带来更好的类型安全性和IDE支持,特别适合TypeScript项目,使代码更易维护。
使用时可选择传统选项式或更灵活的组合式API,复杂组件推荐采用组合式API以获得更好的代码组织。
defineComponent是 Vue 3 中用于定义组件的主要方法,它提供了更好的 TypeScript 类型推断支持。
基本用法
1.选项式 API(类似 Vue 2)
import { defineComponent } from 'vue' export default defineComponent({ name: 'MyComponent', props: { title: { type: String, required: true }, count: { type: Number, default: 0 } }, data() { return { message: 'Hello Vue 3' } }, computed: { doubledCount() { return this.count * 2 } }, methods: { increment() { this.count++ } }, mounted() { console.log('组件已挂载') } })2.组合式 API
import { defineComponent, ref, computed, onMounted } from 'vue' export default defineComponent({ name: 'MyComponent', props: { title: String }, setup(props) { const count = ref(0) const message = ref('Hello Vue 3') const doubledCount = computed(() => count.value * 2) const increment = () => { count.value++ } onMounted(() => { console.log('组件已挂载') }) return { count, message, doubledCount, increment } } })TypeScript 支持
3.完整的 TypeScript 类型定义
import { defineComponent, PropType } from 'vue' interface User { id: number name: string email: string } export default defineComponent({ name: 'UserProfile', props: { // 基本类型 age: { type: Number, required: true }, // 自定义类型 user: { type: Object as PropType<User>, required: true }, // 数组类型 tags: { type: Array as PropType<string[]>, default: () => [] }, // 联合类型 status: { type: String as PropType<'active' | 'inactive' | 'pending'>, default: 'pending' } }, emits: { // 定义 emit 事件 'update:name': (value: string) => true, 'delete': (id: number) => true }, setup(props, { emit }) { // 这里可以获得完整的类型提示 console.log(props.user.name) // 类型安全 const updateName = (name: string) => { emit('update:name', name) } return { updateName } } })多种写法
4.函数式写法
import { defineComponent, h } from 'vue' // 函数式组件 const FunctionalComponent = defineComponent(() => { return () => h('div', 'Hello Functional Component') }) // 带 props 的函数式组件 const Greeting = defineComponent((props: { name: string }) => { return () => h('div', `Hello ${props.name}`) })5.Setup 语法糖(<script setup>)
vue
<script setup lang="ts"> import { defineProps, defineEmits, ref } from 'vue' // 定义 props(自动推断类型) const props = defineProps<{ title: string count?: number }>() // 定义 emits const emit = defineEmits<{ (e: 'update:title', value: string): void (e: 'submit'): void }>() const message = ref('Hello') // 直接使用,不需要 return </script> <template> <div> <h1>{{ title }}</h1> <p>{{ message }}</p> </div> </template>高级用法
6.泛型组件
import { defineComponent, PropType } from 'vue' // 使用泛型定义可复用的组件 function useGenericComponent<T>() { return defineComponent({ props: { items: { type: Array as PropType<T[]>, required: true }, itemFormatter: { type: Function as PropType<(item: T) => string>, default: (item: T) => String(item) } } }) } // 使用 const StringList = useGenericComponent<string>() const NumberList = useGenericComponent<number>()7.与自定义 Hooks 结合
import { defineComponent } from 'vue' import { useUser, useApi } from './composables' export default defineComponent({ name: 'UserProfile', setup() { // 使用自定义组合式函数 const { user, loading, fetchUser } = useUser() const { callApi } = useApi() // 组合多个逻辑 const loadData = async () => { await fetchUser() await callApi('/some-endpoint') } return { user, loading, loadData } } })主要优势
类型推断:为选项式 API 提供更好的 TypeScript 类型支持
类型安全:props、emits、data 等都有完整的类型检查
IDE 支持:更好的代码补全和提示
灵活性:支持多种组件定义方式
注意事项
在
<script setup>中,defineComponent不是必须的,但可以用来包裹组件逻辑对于简单的组件,可以直接使用
defineComponent({})对于复杂组件,建议使用组合式 API 以获得更好的类型支持和代码组织
Vue 3 的defineComponent让组件开发更加类型安全和易于维护,特别是在 TypeScript 项目中优势明显。