npm create vite
生成项目后,文件目录如下:
├── .idea/ # IntelliJ IDEA 配置目录
├── .vscode/ # VS Code 配置目录
├── public/ # 静态资源目录
│ └── vite.svg # Vite 默认图标
├── src/ # 源代码目录
│ ├── assets/ # 项目资源文件
│ │ └── vue.svg # Vue 图标
│ ├── components/ # Vue 组件目录
│ │ └── HelloWorld.vue # Hello World 组件
│ ├── App.vue # 主应用组件
│ ├── main.ts # 应用入口文件
│ ├── style.css # 全局样式文件
│ └── vite-env.d.ts # Vite 环境类型声明
├── index.html # HTML 入口文件
├── package.json # 项目配置和依赖管理
├── README.md # 项目说明文档
├── tsconfig.json # TypeScript 基础配置
├── tsconfig.app.json # TypeScript 应用配置
├── tsconfig.node.json # TypeScript Node.js 配置
├── vite.config.ts # Vite 构建工具配置
└── .gitignore # Git 忽略文件配置
Button.vue
<template>
<button
ref="_buttonRef"
class="ms-button"
:disabled=disabled
:autofocus=autofocus
:type=nativeType
:class="{
[`ms-button--${type}`]: type,
[`ms-button--${size}`]: size,
'is-plain': plain,
'is-round': round,
'is-circle': circle,
'is-disabled': disabled,
}">
<slot>slot>
button>
template>
<script setup lang="ts">
import {type ButtonProps} from "./type";
import {onMounted, ref} from "vue";
const _buttonRef = ref<HTMLButtonElement>();
onMounted(()=>{
console.log('buttonRef === ', _buttonRef.value)
})
//宏函数
defineOptions({
name: 'MsButton'
})
withDefaults(defineProps<ButtonProps>(),{
nativeType: 'button'
})
defineExpose({
buttonRef: _buttonRef
})
script>
<style scoped>
style>
type.ts
export type ButtonType = 'primary' | 'info' | 'success' | 'warning' | 'danger';
export type ButtonSize = 'large' | 'small';
export type NativeType = 'button' | 'submit' | 'reset'
export interface ButtonProps {
type?: ButtonType,
size?: ButtonSize,
nativeType?: NativeType,
plain?: boolean,
round?: boolean,
circle?: boolean,
disabled?: boolean,
autofocus?: boolean,
}
在 Vue 3 中,宏函数(Macros) 是特殊的编译时函数,它们在代码被浏览器执行前就被 Vue 编译器处理,主要服务于 语法糖。这些函数不是普通的 JavaScript 函数,而是 Vue 编译器识别的特殊标记,用于声明组件选项或执行编译时优化。
以下是 Vue 3 的核心宏函数详解:
的顶层使用,不可嵌套在函数内defineProps
- 声明组件 Props
编译后效果:
转换为标准的 props
组件选项
生成类型安全的 Props 验证代码
defineEmits
- 声明组件事件
用法:
emit('update:title', 'New Title') // 触发事件
defineExpose
- 暴露组件公共属性
父组件调用:
defineOptions
(Vue 3.3+) - 设置组件选项
defineSlots
(Vue 3.3+) - 类型化插槽
特性 | 宏函数 (如 defineProps ) |
普通函数 (如 ref ) |
---|---|---|
执行时机 | 编译阶段处理 | 运行时执行 |
代码位置 | 必须位于 顶层 |
可出现在任意位置 |
类型支持 | 完整 TS 类型推导 | 需手动标注类型 |
输出结果 | 被编译器替换为选项 API | 生成实际 JavaScript 代码 |
可组合性 | 不可组合使用 | 可组合到自定义 hook 中 |
以 defineExpose
为例的编译过程:
输入 (源代码):
输出 (编译后):
export default {
setup() {
const __returned__ = { count: 0 }
// 编译器注入的暴露逻辑
Object.assign(__returned__, {
__exposed: __returned__
})
return __returned__
},
// 特殊标记
__expose: true
}
避免在逻辑块中使用
// ❌ 错误!宏不能在函数内使用
function init() {
defineProps({ /*...*/ })
}
组合式 API 优先
宏函数应配合 ref
/computed
等组合式 API 使用
类型声明优先于运行时声明
使用 TypeScript 时选择类型声明方式:
// ✅ 推荐
defineProps<{ title: string }>()
// ⚠️ 次选
defineProps({ title: String })
与普通函数区分使用
版本兼容注意
defineOptions
/defineSlots
需 Vue 3.3+unplugin-vue-define-options
兼容Vue 3 的宏函数是现代化组件开发的基石,它们:
理解宏函数的编译时特性,能帮助开发者更高效地构建健壮且类型安全的 Vue 3 应用。