Vue的props和emits -- 组件通信
props和emits之间的组件通信
数据流向
- props:父组件 → 子组件(数据下行)
- emit:子组件 → 父组件(事件上行)
核心机制
- props:父组件通过属性传递数据给子组件
- emit:子组件通过事件向父组件发送消息
设计模式
单向数据流:
父组件 --props--> 子组件 --emit--> 父组件
完美配合
- props 传递状态数据
- emit 通知状态变更
- 共同实现可复用、可维护的组件化架构
这就是Vue组件间通信的基础模式!
分项解释
分项解释1 - Props
在Vue中,props(属性) 是父组件向子组件传递数据的自定义属性。
主要特点:
- 单向数据流:数据只能从父组件流向子组件,子组件不能直接修改props
- 可配置性:可以定义类型验证、默认值、是否必需等
- 组件通信:实现父组件与子组件的数据传递
示例:
<!-- 子组件 -->
<script setup>
defineProps({
title: String,
count: {
type: Number,
default: 0
}
})
</script>
<!-- 父组件使用 -->
<ChildComponent title="Hello" :count="5" />
props使得Vue组件可以复用并接收不同的数据,是组件化开发的核心概念之一。
分项解释2 - Emits
在Vue中,emit(发射) 是子组件向父组件传递消息的方法。
主要特点:
- 子传父:子组件通过事件通知父组件
- 触发父组件方法:父组件可以监听子组件发出的事件并执行相应逻辑
- 可传递数据:可以携带数据传递给父组件
示例:
<!-- 子组件 -->
<script setup>
// 1. 定义emit函数(获取发射事件的能力) - emit(事件名称, 传递的数据)
const emit = defineEmits(['update'])
function handleClick() {
// 2. 使用emit函数来发射事件
emit('update', newValue) // 这里是调用上面定义的emit函数
}
</script>
<!-- 父组件 -->
<ChildComponent @update="handleUpdate" />
emit与props配合,实现了Vue组件间的双向通信机制。
分项解释3 - @update和@input
相同点
- 都是事件监听语法
- 都使用
@符号作为简写 - 都用于响应某个动作
不同点
@input
- 原生DOM事件(浏览器内置)
- 浏览器自动触发(用户输入时)
- 主要用于表单元素
<input @input="handleInput" />
<!-- 用户输入时自动触发 -->
@update
- 自定义组件事件
- 需要子组件手动触发(通过
emit) - 用于组件间通信
<!-- 子组件内部 -->
emit('update', data)
<!-- 父组件使用 -->
<ChildComponent @update="handleUpdate" />
总结
@input:监听浏览器原生输入事件@update:监听子组件自定义事件
一个是"被动监听",一个是"主动通知"的关系!
分项解释4 - @update:modelValue
这是Vue中v-model的自定义实现语法:
- 用于实现自定义组件的v-model
- 是Vue 3中v-model的底层机制
传统v-model等价关系
<!-- 这两种写法是等价的 -->
<CustomInput v-model="searchText" />
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
完整示例
子组件
<script setup>
// 定义组件接收的属性:一个名为modelValue的prop(来自父组件v-model绑定的值)
defineProps(['modelValue'])
// 定义组件可以发射的事件:一个名为update:modelValue的自定义事件
defineEmits(['update:modelValue'])
// 处理输入框输入事件的函数
function updateValue(event) {
// 发射update:modelValue事件,将输入框的新值传递给父组件
// event.target.value是输入框当前的值
emit('update:modelValue', event.target.value)
}
</script>
<template>
<!--
输入框组件:
:value="modelValue" - 将输入框的值绑定到从父组件传来的modelValue
@input="updateValue" - 当输入框有输入时,触发updateValue函数
-->
<input
:value="modelValue"
@input="updateValue"
/>
</template>
父组件
<CustomInput v-model="text" />
<!-- 等价于 -->
<CustomInput
:modelValue="text"
@update:modelValue="newValue => text = newValue"
/>
数据流向说明:
父组件 v-model="text"
→ 子组件 :modelValue="text" (props传入)
→ 用户输入 → @input触发 → emit发射事件
→ 父组件 @update:modelValue接收 → 更新text
总结
@update:modelValue 是v-model的事件监听部分,用于接收子组件的数据更新通知!
Vue3 最新的父子通信(双向绑定)方式
Vue 3.4+ 官方文档 推荐使用 defineModel,大大简化了双向绑定的实现。
新旧对比
旧方式(复杂)
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
function updateValue(event) {
emit('update:modelValue', event.target.value)
}
</script>
<template>
<input
:value="modelValue"
@input="updateValue"
/>
</template>
新方式(简洁)
<script setup>
const modelValue = defineModel()
</script>
<template>
<input v-model="modelValue" />
</template>
defineModel 的优势
- 一行代码搞定:替代了
defineProps+defineEmits+ 更新函数 - 直接使用 v-model:在模板中可以直接用
v-model绑定 - 类型安全:更好的 TypeScript 支持
- 更直观:逻辑更清晰易懂
使用方法
基本用法
<script setup>
const value = defineModel()
</script>
<template>
<input v-model="value" />
</template>
带默认值和类型
<script setup>
const count = defineModel({ default: 0, type: Number })
</script>
结论
Vue 3.4+ 强烈推荐使用 defineModel,不再需要手动拆解 props 和 emit,代码更加简洁优雅!
这是 Vue 双向绑定演进的重要改进!

浙公网安备 33010602011771号