vue3中使用 defineProps 和 defineEmits
·
在 Vue 3 + JavaScript 环境中,defineProps 和 defineEmits 是 <script setup> 语法糖中用于声明组件 props 和自定义事件的编译时宏。以下是详细用法说明和示例。
一、defineProps —— 声明父传子的数据
基本用法
<script setup>
// 基础写法:数组形式(不推荐,无类型校验)
const props = defineProps(['title', 'count'])
// 对象形式(推荐,可添加校验)
const props = defineProps({
title: String,
count: {
type: Number,
required: true,
default: 0
},
isShow: {
type: Boolean,
default: false
}
})
</script>
<template>
<div>
<h2>{{ title }}</h2>
<p>Count: {{ count }}</p>
<p v-if="isShow">显示内容</p>
</div>
</template>
常用校验选项
| 选项 | 说明 |
|---|---|
type |
数据类型(String/Number/Boolean/Array/Object/Function) |
required |
是否必传 |
default |
默认值(对象/数组需用函数返回) |
validator |
自定义校验函数 |
age: {
type: Number,
validator: (value) => value >= 0 && value <= 150
}
二、defineEmits —— 声明子传父的事件
基本用法
<script setup>
const emit = defineEmits(['change', 'submit'])
const handleClick = () => {
emit('change', '新值')
emit('submit', { id: 1 })
}
</script>
<template>
<button @click="handleClick">触发事件</button>
</template>
对象写法(支持校验)
const emit = defineEmits({
change: (payload) => typeof payload === 'string',
submit: null // 无校验
})
三、完整示例(父子组件通信)
子组件 Child.vue
<script setup>
const props = defineProps({
msg: {
type: String,
default: 'Hello'
}
})
const emit = defineEmits(['reply'])
const sendReply = () => {
emit('reply', '来自子组件的消息')
}
</script>
<template>
<div>
<p>{{ msg }}</p>
<button @click="sendReply">回复父组件</button>
</div>
</template>
父组件 Parent.vue
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const message = ref('父组件消息')
const handleReply = (val) => {
console.log(val)
}
</script>
<template>
<Child :msg="message" @reply="handleReply" />
</template>
四、注意事项(非常重要)
- 只能在
<script setup>中使用 - 无需导入(编译器自动处理)
- props 是只读的(不能直接修改)
- 事件名推荐使用 kebab-case
- 不支持 TypeScript 时,对象写法更灵活
五、与 options API 对比
| 特性 | defineProps / defineEmits | props / emits 选项 |
|---|---|---|
| 语法 | 编译宏 | 选项式 |
| 类型推断 | 一般 | 较弱 |
| 代码简洁度 | ✅ 更高 | ❌ 较冗余 |
| 是否推荐 | ✅ Vue 3 首选 | ⚠️ 兼容写法 |
如果你需要 TypeScript 版本、默认值合并技巧 或 与 v-model 结合使用,可以继续问我 👍
更多推荐


所有评论(0)