外观
Vue 组件怎么通信?
父子用 props 向下、事件向上。隔了多层再考虑 provide / inject。没有父子关系、又要共享一份会变的状态时,用 Pinia,而不是全局事件总线。
原理
父组件把数据放进属性,子组件用 defineProps 声明类型和默认值。子组件要改父组件的数据时,发出事件,父组件改自己的状态。不要在子组件里直接改 props。
v-model 是属性和 update:modelValue 事件的约定。一个组件可以有多个 v-model。
provide 可以提供响应式对象。注入方只读,修改仍由提供者负责,否则数据从哪改的会散掉。默认值只在没有提供者时使用。
插槽是父组件把模板交给子组件渲染,适合布局。作用域插槽让子组件把内部数据交回给父组件的模板。见 插槽。
跨页面的「用户信息、购物车」用状态库。事件总线只适合真正的广播,并且要在卸载时关掉。见 发布订阅。
追问
$parent 和 ref 呢?
能用,但父子就焊死了。只在命令式地让子组件聚焦、滚动时用模板 ref。不要用 $parent 去读父组件的数据。
props 太深怎么办?
先看是不是组件拆得过碎。剩下的跨层只读配置用 provide。会频繁改、很多地方写的状态用状态库。
易错点
- 子组件改 props 对象的字段。对象是引用,父组件的数据会被悄悄改掉。
provide提供了一个普通对象,之后整体替换这个对象,注入方看不到。提供ref或reactive。- 用事件总线传递常规表单数据,来源无法追踪。