在 Vue 3 的 Composition API 生态中,编译宏(Compiler Macros)是一组特殊的语法结构,它们在代码编译阶段被 Vue 编译器处理,最终转换为标准的 JavaScript 代码。这些宏函数是 Vue 3 语法糖的核心组成部分,主要包含:
defineProps
:声明组件 propsdefineEmits
:定义自定义事件defineExpose
:暴露组件公共方法defineOptions
:配置组件选项defineSlots
:声明插槽类型(TypeScript 专用)withDefaults
:为 props 提供默认值Vue 团队引入编译宏的核心目标:
特性 | 选项式 API | 编译宏 |
---|---|---|
代码位置 | export default 对象 |
顶层 |
类型支持 | 有限 | 完整的 TypeScript 支持 |
作用域访问 | 通过 this |
直接访问上下文变量 |
编译阶段处理 | 无 | 深度静态分析 |
代码组织 | 按选项分类 | 按逻辑关注点组织 |
defineProps
的编译魔法
interface Props {
title: string
count?: number
}
const props = defineProps<Props>()
// 编译前
defineProps({ title: String })
// 编译后
export default {
props: {
title: {
type: String
}
},
setup(props) {
// ...其他逻辑
}
}
defineEmits
的事件系统// 选项式 API
emits: ['update:modelValue']
// 编译宏方式
const emit = defineEmits(['update:modelValue'])
// 完整类型声明
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
(e: 'submit'): void
}>()
// 错误示例:类型不匹配会触发编译错误
emit('update:modelValue', 123) // 报错:类型 number 不能赋值给 string
// 正确用法
emit('update:modelValue', 'new value')
defineExpose
的组件通信// 选项式 API
export default {
methods: {
publicMethod() { /*...*/ }
}
}
// 编译宏方式
const internalState = ref(0)
defineExpose({
publicMethod: () => {
// 访问内部状态
internalState.value++
}
})
// 父组件模板
<ChildComponent ref="childRef" />
// 子组件
defineExpose({
validate: (): boolean => { /*...*/ }
})
// 父组件类型提示
const childRef = ref<{
validate: () => boolean
}>()
// useFormValidation.ts
export default function () {
const errors = reactive<string[]>([])
const validate = () => {
// 验证逻辑
}
return {
errors,
validate
}
}
// 组件中使用
const { errors, validate } = useFormValidation()
defineExpose({ validate })
type ComplexProp<T> = {
data: T
transformer: (raw: T) => string
}
const props = defineProps<ComplexProp<number[]>>()
type ResponsiveProp<T> = T | Ref<T> | ComputedRef<T>
defineProps<{
width: ResponsiveProp<string>
}>()
function createProps<T extends Record<string, any>>(schema: T) {
return defineProps(schema)
}
// 使用工厂函数
const props = createProps({
size: {
type: String as PropType<'small' | 'medium' | 'large'>,
default: 'medium'
}
})
标签defineProps
等转换为标准选项// 伪代码展示编译转换过程
function compileSetupScript(code) {
return code
.replace(/defineProps\(([^)]+)\)/g, 'export const props = $1')
.replace(/defineEmits\(([^)]+)\)/g, 'export const emits = $1')
}
// 错误:在函数内部使用
function init() {
defineProps({ /*...*/ }) // 编译错误
}
// 正确:必须在顶层作用域
defineProps({ /*...*/ })
// 错误示例:使用动态参数
const config = { title: String }
defineProps(config) // 编译失败
// 正确:必须使用字面量
defineProps({ title: String })
// global.d.ts
declare module 'vue' {
interface GlobalComponents {
CustomInput: typeof import('./components/CustomInput.vue')['default']
}
}
// macros.d.ts
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$customMethod: () => void
}
}
// tsconfig.json
{
"compilerOptions": {
"types": ["vite/client", "@vue/runtime-core"],
"strict": true,
"skipLibCheck": true
}
}
// .eslintrc.js
module.exports = {
rules: {
'vue/define-props-declaration': ['error', 'type-based']
}
}
通过深入理解和正确应用 Vue 3 的编译宏系统,开发者可以显著提升组件开发的效率与代码质量。这些宏函数不仅是语法糖,更是 Vue 团队对开发者体验持续优化的结晶。随着生态工具的不断完善,编译宏将在 Vue 应用的架构设计中扮演越来越重要的角色。