组件通信
1、父组件 => 子组件
- 属性props
// child props: { msg: String } // parent <HelloWorld msg="Welcome to Your Vue.js App"/>
- 引用refs --- 特别适用于想要操作某些DOM结构时,refs就是这些DOM节点
// parent <HelloWorld ref="hw"/> this.$refs.hw.xx = 'xxx'
this.$refs 需要在mounted 中 或之后调用,因为父组件先于子组件挂载,在父组件 created 的时候,子组件还没挂上去,所以访问不到
- 子组件chidren
// parent this.$children[0].xx = 'xxx'
子元素不保证顺序,需要小心使用
2、子组件 => 父组件 自定义事件
// child this.$emit('add', good) // parent <Cart @add="cartAdd($event)"></Cart>
3、兄弟组件:通过共同祖辈组件
通过共同的祖辈组件搭桥,$parent 或 $root
// brother1 this.$parent.$on('foo', handle) // brother2 this.$parent.$emit('foo')
4、祖先和后代之间
由于嵌套层数过多,传递props不切实际,vue提供了 provide/indect API完成该任务
- provide / inject:能够实现祖先给后代传值
// ancestor provide() { return {foo: 'foo'} } // descendant inject: ['foo']
注意:provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序中。我们更多会在开源组件库中见到。
但是,反过来想要后代给组件传值,这种方案就不行了,子组件如果想改的话,需要组件在provide中注入 setFoo 的函数,子组件通过setFoo来修改 foo 的值
provide的时候,完全可以把当前组件(祖先组件)注入,直接传入 this 就行了
5、任意两个组件之间:事件总线 或 vuex
- 事件总线:创建一个 Bus 类负责事件派发、监听 和 回调管理
// Bus:事件派发、监听和回调管理 class Bus { constructor() { this.callbacks = {}; } $on(name, fn) { this.callbacks[name] = this.callbacks[name] || []; this.callbacks[name].push(fn); } $emit(name, args) { if (this.callbacks[name]) { this.callbacks[name].forEach(cb => cb(args)); } } } // main.js Vue.prototype.$bus = new Bus(); // 使用 // child1 this.$bus.$on("foo", handle); // child2 this.$bus.$emit("foo");
简单点的写法: Vue.prototype.$bus = new Vue()
这里的 new Vue() 是一个新的、干净的vue实例,只在做监听、派发消息的事情。因为Vue已经实现上述 Bus 的接口了
- vuex:创建唯一的全局数据管理者 store,通过它管理数据并通知组件状态变更