一、props
props不仅可以实现父给子传递信息,还可以进行子给父传递信息
1.父给子传递信息:
父组件中给子组件实例传递信息
子组件利用props进行接收组件传递信息(接收方式有三种:数组、对象、配置对象)
2.子给父传递信息 (可以利用嵌套从孙组件传递给父组件)
提前在父组件中声名一个函数带传递参数
绑定在子组件(多层组件需要进行嵌套)v-bind、:
子组件进行接收绑定的函数
子组件创建发送数据函数(其中调用传入的接收函数)
将子组建的函数通过事件绑定在指定模板标签中@
//父组件获取数据
checkTodo (id) {
this.todos.forEach((todo) => {
if (todo.id === id) todo.done = !todo.done
});
}
//将获取数据的方法绑定在子组件(这里就运用了组件嵌套传递)
<MyList :checkTodo='checkTodo' />
<MyItem :checkTodo='checkTodo' />
props: ['checkTodo']
//子组件中获取数据
props: ['checkTodo'],
//子组件中创建发送数据的方法并绑定事件执行此函数(传参)
<input @change='handleCheck(todo.id)' />
handleCheck (id) {
this.checkTodo(id)
}
二、自定义事件(子给父传递数据)
自定义事件使用流程
1. 直接在父组件中给子组件实例绑定自定义事件,定义事件的回调,绑定方式v-on、@
此时需要注意自定义事件的名字是自己命名的
如果只需要执行一次还可以使用事件修饰
<Studnt v-on:xlf.once="getStudentName" @demo="demo" />
2. 还有一个自定义事件的绑定给组件实例方法:通过ref进行绑定
ref绑定优势:可以利用定时器延时绑定:比较灵活
setTimeout(() => { this.$refs.Student.$on('xlf', this.getStudentName) }, 3000)
首先给组件实例添加ref标识
如果存在内置事件使用,需要在自定义事件后添加@native,否则就需要向以下执行方式一样利用$emit()
<Student ref='Student' @click.native="show" />
在组件挂载钩子的时候执行绑定自定义事件$on('组件名',回调函数)
此时自定义回调要么直接写在$on()中,但是必须要用你箭头函数
因为使用普通函数谁触发了此事件回调中的this就会指向触发的组件实例
还有一种方式提前设置回调函数,然后再$on()中直接调用
mounted () { this.$refs.Student.$on('xlf', this.getStudentName) }
3. 在父组件中创建自定义事件的回调函数:可以接收两个参数
自定义事件名字
传递的参数
getStudentName (name, ...params) { console.log('app收到了学生名', params); this.StudentName = name//传递进来的数据赋值给data中的属性 }, //用于自定义事件的回调函数 demo () { console.log('demo事件被触发'); },
4.在子组件中绑定事件并执行发送数据函数
<button @click="sendStudentName">点我获取学生名</button>
5. 在子组件中创建发送数据并直接使用方法:this.$emit('组件名字',其他多个参数)
sendStudentName () { // $emit:触发,爆发 // 触发student实例对象的方法 // 添加更多属性值:包装成对象或者将接收换成剩余参数 this.$emit('xlf', this.name, 666) this.$emit('demo') },
6.在组件销毁之前或者其他情况需要解绑自定义事件:$off()
this.$off('事件名'):解绑指定自定义事件
this.$off(['事件名1', '事件名2']):解绑多个指定自定义事件
this.$off():解绑所有自定义事件
unbind () { //只适用解绑一个事件 this.$off('xlf') // 解绑多个自定义事件,需要将多个自定义事件写入数组中 // this.$off(['xlf', 'demo']) // 解绑的所有事件 // this.$off() },
注意:如果需求将子组件延时全部销毁:需要再入口main.js文件中使用
mounted() { setTimeout(() => { //自杀 this.$destroy() },3000) }
三、全局事件总线(任意组件之间的通信)解决兄弟直接通信
1. 读取以下文字并理解兄弟组件传递流程
-
A组件内中收到别人数据,需要在a组件中,给x绑定自定义事件demo,自定义事件的回调函数在a组件中(接收数据处)
-
d组件给a传递数据:d组件中触发x身上的demo自定义事件并传递参数
此时的x不属于任何组件:但是所有组件都可以看到
还需要x可以调用:$on,$emit,$off
2. 实现x能被所有组件看到:这时候需要在入口Vue初始化时候就注册全局事件总线
利用组件实例对象的__protp__=vue原型,此时的vm还有vc都可以看到注册的x
在vue中将总线绑定在当前实例
x是vue中的$bus
beforeCreate () { // 利用钩子(实例化未进行数据绑定)安装全局总线,vue原型对象上添加一个$bue=当前vue实例 Vue.prototype.$bus = this//安装全局事件总线应该在app组件解析过程中而不是解析完成之后,此时的所有vc和vm都可以看到 }
3. 确保$on,$emit,$off都可以使用并进行兄弟间组件通信
在注册全局事件总线之后
在兄组件中给全局事件总线绑定自定义事件$on('组件名',回调函数)
//兄:获取数据在全局事件总线上绑定自定义事件 mounted () { // 给总线绑定自定义事件,回调函数在当前组件,如果绑定事件的回调函数直接写在$on中,那么使用箭头函数 this.$bus.$on('hello', (data) => { console.log('我是school组件,收到了数据', data) }) },
在子组件中调用自定义事件并进行传递数据
//模板绑定事件并执行函数 <button @click="sendStudentName">学生名给school组件</button> //声名方法调用全局总线中的自定义事件 methods: { // 通过全局总线的自定义事件进行发送数据 sendStudentName () { this.$bus.$emit('hello', 666) } },
绑定事件总线的自定义事件需要在组件销毁前解绑
beforeDestroy () { this.$bus.$off('hello') },
注意:利用全局总线绑定自定义事件命名不可以重复
解决:利用一个文件config:在文件中使用某些方式表示当前名字已出现在全局事件总线
四、消息订阅与发布(任意组件之间的通信)
执行消息订阅与发布:
首先执行消息的订阅
接着执行数据的发布
注意:需要引入第三方库:pubsub-js
先进行安装:npm i pubsub-js
然后引入使用
1. 订阅:
引入pubsub
利用api:pubsub.subscrib进行绑定自定义事件(’事件名‘,回调 ),回调可以提前声名,并给其绑定事件一个pubsub的ID
需要销毁订阅:使用pubsub.unsubscribe(绑定事件的id)
注意:回调箭头函数如果直接使用this指向的是undefined,因为是第三方模块,可以利用提前声名的方法
注意:接收参数,会收到自定义事件名字,可以使用占位符进行占位
// 1. 安装好pubsub-js之后引入pubsub import pubsub from 'pubsub-js' //2. 订阅消息 methods: { // 此处时订阅消息的回调函数 //demo (msgName, data) demo (_, data) { console.log('消息收到', msgName, data); } mounted () { // 订阅消息(注意给订阅id,因为需要被销毁) //参数是消息名,参数 this.pubId = pubsub.subscribe('hello', this.demo) } //3. 销毁订阅消息:使用api进行取消订阅(注意订阅名字) beforeDestroy () { // this.$bus.$off('hello') pubsub.unsubscribe(this.pubId) },
2.发布
引入pubsub
绑定一个发送数据的方法给当前组件中
执行发布api:pubsub.publish('发布的自定义事件名字',参数)
//1.引入pubsub import pubsub from 'pubsub-js' //2.兄弟组件绑定一个事件并执行回调函数 <button @click="sendStudentName">学生名给school组件</button> //3.回调函数中执行自定义事件并传入参数(发布订阅) methods: { sendStudentName () { pubsub.publish('hello', 666) } },