Props 单向流动(父→子),但可通过传递回调函数实现子→父通信;父组件定义函数并传入子组件,子组件调用该函数触发父组件更新,虽可行但耦合高、语义弱,官方推荐优先使用 defineEmits + $emit。

Props 本身是单向的(父→子),但可以通过传递函数的方式,让子组件调用父组件的方法,从而实现“子→父”的逆向通信。这不是 props 的本意用法,但原理清晰、调试方便,适合简单场景或快速验证逻辑。
父组件定义并传入回调函数
在父组件中声明一个函数,通过 props 传给子组件。这个函数接收子组件传来的参数,并更新父组件自身的响应式数据。
- 使用 ref 或 reactive 定义需要被更新的状态
- 定义一个普通函数,参数即子组件要传递的数据(如字符串、对象、事件值等)
- 在模板中将该函数作为 prop 绑定到子组件上,注意用冒号
:触发响应式绑定
子组件接收并调用回调函数
子组件通过 defineProps 声明接收的函数类型 prop,在合适时机(比如按钮点击、输入变化、生命周期钩子)调用它。
- props 类型建议标注为
Function,增强可读性和类型安全(尤其在 TS 环境) - 调用时传入实际数据,如
props.onUpdate('new value') - 避免在 setup 中直接修改 props,只用于触发父级逻辑
注意事项与边界提醒
这种写法虽可行,但要注意它和 Vue 官方推荐的 emit 方式有本质区别:
立即学习“前端免费学习笔记(深入)”;
- emit 更语义化:子组件明确“发出事件”,父组件明确“监听事件”,职责分离更干净
- props 传函数易造成耦合:子组件需知道父组件函数名和参数结构,不利于复用
-
不支持事件修饰符或原生事件对象:比如无法像
@click.stop那样处理 DOM 事件细节 - 深层嵌套时,中间组件仍需透传该函数,不如
provide/inject简洁
替代建议:优先考虑 emit
对于标准父子通信,应优先使用 defineEmits + $emit:
- 子组件用
const emit = defineEmits(['update'])声明事件 - 触发时写
emit('update', payload) - 父组件用
@update="handleUpdate"监听


















