组件通信小结
组件通信的方式:
1.最基本的组件交互/组件通信方式
props:
props可以实现组件之间的数据(属性or方法)传输,但是对于跨级的
数据传输依然需要逐层传递与接收,所以缺点就是不需要数据的组件
依然需要承担数据传输的责任,导致组件标签上绑定了太多的传值属
性这种方式也就是需要"自定义标签属性"来实现传递数据
props应该注意的地方:
a.不要随意的修改props,把它当作只读的!藏在对象中的数据改变vue
是监视不到的,如果不是对象就会报错,所以在需要修改props传递的
数据时应该借助中间值修改:如 a --> b -->修改
b.props只适合 父-->子 的数据传递方向
2.基于回调函数的组件交互
这种方式依旧需要借助props来传递数据,不过此时传递的数据是一个函数,当
这个函数传递到发送数据的组建后,发数据的组件就可以通过诸如click类的
事件使用传递过来的函数,达到传递数据的目的
3.基于事件的组件通信
这种通信依赖于"自定义组件事件",为什么要去自定义事件呢? js有内置的事件
可以使用,而组件没有,就需要去自定义(这么说也不对,其实也可以用...具体原因
我还没有去想,总归可以达到数据的交互)
实现方式:
组件上需要绑定自定义事件,然后由发送数据的组件去触发该事件
例如给Student组件绑定事件,有两种方式:
a. <Student @sakura="getStudentName"/>
b. <Student ref="student"/>
mounted() {
/*在Student的vc实例对象绑定sakura事件*/
this.$refs.student.$on('sakura',this.getStudentName)
}
这两种方式都需要去解除事件
a. this.$off(['sakura','demo'])
this.$off()
b. this.$destroy() //自杀
这两种方式都可解绑事件,组件在父容器定义,在父容器中绑定事件,
事件的触发则需要子组件去做
弊端:只能实现父子,爷孙 ... 之间的数据交互,不能解决兄弟间的交互
4.全局事件总线$bus
$bus只是起了方便的名字而已,以做区别.
它解决了兄弟组件间的数据交互,全局事件总线是解决第三方的组件来实现交互的,好像
两个关在房间里的人,他们想说话,但是对方都听不见,所以就借助一个具有一定作用的第
三者来实现彼此间的通信.
那么这种通信基于: VueComponent.prototype.__proto__ === Vue.prototype
这一条内置关系来实现的,这条关系让所有vm的子组件,子孙组件都可以看到vm里的东西
所以把vm作为第三者来传递数据再好不过了,因为子孙组件都可以看见(使用)
现在给Vue.prototype上绑定一个属性,让所有组件都可以看见
实现有两种:
1. 如:绑定一个 x
Vue.prototype.x = {a:'1',c:'hello'}
这样子组件可以看到,但是如何在一个属性 x 上去绑定事件并且,其它组件可以
触发呢? 显然是办不到的
那么这个 x应该具备什么样的功能才能承担起,这个第三者?
1.可见性 可用性
2.具备 $on 用于事件绑定
3.具备 $off 用于解绑事件
4.具备 $emit 用于事件触发
基于以上几点,目标就是VueComponent,Vue者两个大哥了
VueComponent要通过Vue.extend({})去创建,然后new出来才是一个
VueComponent实例对象(等同去写一个<Student/>组件时才会去new出
VueComponent实例),然后绑定到Vue.prototype上就可以实现那个第三
者,但是这样写不够优雅
2.在Vue的原型上绑定vm
new Vue({
/*将App挂载到容器上*/
render:h=>h(App),
beforeCreate() {
Vue.prototype.$bus = this //绑定事件总线$bus
}
}).$mount('#app')
5.消息订阅与发布
谁需要消息谁就去订阅:
订阅时机-->mouted
1.解除订阅时机-->beforeDestroy()与事件总线解除事件一样
(为什么解除:如果组件过多,$bus或pubsub上的职能过多,在组件解除时就应解除订阅)
mounted() {
//this.$bus.$on('delTodo',this.delTodo)
this.pubId = pubsub.subscribe('delId',this.delTodo)
},
//组件销毁解绑事件
beforeDestroy() {
//this.$bus.$off('delTodo')
pubsub.unsubscribe(this.pubId)
}
2.发布订阅:消息的发布者(消息来源)
handleDeleteTodo(id){
if(confirm('confirm to delete this todo')){
//this.$bus.$emit('delTodo',id) //触发事件
pubsub.publish('delId',id) //发布订阅
}
}
6.slot prop(插槽prop)
在slot标签上绑定属性传递数据给数据的使用者
数据的使用者可使用scope=""或slot-scope=""或v-slot=""接收数据使用
接受的数据可以起别名,然后 . 去使用,也可以通过解构赋值接收
注:基于事件的组件交互,谁要发数据谁就去触发事件并携带数据(需要的话)