组件通信有哪些方式,怎么选?
先理解原理和示例,再练习完整口述与追问。
回答要点
父子优先 props / events,内容定制用插槽,跨层可用 provide / inject,跨页面共享状态用 Vuex。$refs 属于命令式调用,应有明确边界;事件总线要考虑依赖隐蔽、解绑和调试成本。
原理拆解
通信方案首先看状态归属和组件关系。父给子传 props,子通过事件表达意图;需要交换渲染内容用插槽;跨多层但属于同一功能范围的依赖可以注入;跨页面共享且有生命周期的数据可进入 Vuex。事件总线隐藏了发送和接收关系,订阅还要手动释放,规模大时更难追踪。
示例与推演
搜索面板接收 appliedFilters 作为展示输入,编辑中的 draft 留在组件内,点击提交后 emit search(draft);父页面决定请求和分页。若用户信息被导航、头像和权限页共享,放到用户 store 更合适。弹窗是否打开若只属于一个页面,不必为了“统一”放进全局 store。
易错点
不能把所有数据都上升到全局,也不应让深层子组件直接修改不透明的父级对象。Vue2 provide 的值并非无条件自动变成响应式,应区分提供的是已观察对象还是普通值。
参考回答可直接练习口述
父子通信我优先用 props 传数据、子组件 emit 通知变化;兄弟共享可提升到共同父级;跨层的组件族可以用 provide/inject;跨页面、跨业务模块的共享状态再放 Vuex。插槽负责内容扩展,ref 适合聚焦等少量命令式操作。事件总线可以使用,但必须明确注册、解绑和事件来源,否则维护时很难追踪数据流。
面试官可能继续问追问与完整解答展开收起
追问
兄弟组件怎样通过公共父级通信?Vue2 的 provide / inject 为什么不能笼统说自动响应式?
追问回答
兄弟组件通常由公共父级维护状态,并把某个子组件事件转成另一个子组件输入。Vue2 的 provide/inject 绑定本身不是自动响应式的;如果提供的是已经被观察的对象,其已有响应式属性仍能驱动更新,但替换提供方的普通值不会自动建立同样的关联。