1. 父子组件通信全景表
| 场景 | 核心技术 | 动作性质 | 记忆口诀 |
|---|---|---|---|
| 子用父变量 | Props | 被动接收 | 父传子,子只读 |
| 父用子变量 | Template Ref | 主动读取 | 父拿 Ref,子需 Expose |
| 子用父函数 | Emits | 向上汇报 | 子喊口令,父来执行 |
| 父用子函数 | Template Ref | 主动指令 | 父下命令,子去执行 |
2. 详细解答:父组件如何使用子组件函数?
答案是:主要通过 ref(主动),而不是 emit(被动)。
方式 A:通过 ref 调用(最常用 - 主动模式)
这是你最需要掌握的。父组件通过 ref 获取子组件实例,直接“点”出子组件的方法。
- 前提:子组件必须通过
defineExpose把函数暴露出来。
JavaScript
// 子组件 Child.vue
const clearInput = () => { /* 逻辑 */ };
defineExpose({ clearInput }); // 关键:开门放行
// 父组件 Parent.vue
const childRef = ref(null);
childRef.value.clearInput(); // 关键:父组件主动下令
方式 B:通过 emit(严格来说是“间接触发” - 被动模式)
emit 通常不被说成“父调用子函数”。但有一种特例:父组件改变了一个变量,子组件 watch 这个变量并触发了自己的函数。这是一种间接的通信。
3. 深度纠正:ref 与 emit 的本质区别
为了防止混淆,你可以这样记:
-
emit是“下级向上级打报告” :子组件:“报告老板!用户点击了上传按钮,你看看该怎么处理(执行父组件函数)?”
-
ref是“上级给下级下指令” :父组件:“小王(子组件),把你那边的输入框给我清空一下(执行子组件函数)!”
4. 你的项目架构复习(Store 模式)
既然你已经重构了 inputField.js,你会发现上面的规则在业务逻辑中被简化了:
- 以前:父组件通过
ref调子组件的reset()函数。 - 现在:父组件和子组件都直接调
inputStore.resetInputField()。
结论:在你的新架构中,组件方法(UI 相关)依然用 ref 和 emit;业务逻辑(数据相关)全部改用 Store Actions。