vue学习笔记06
学习的课程地址:老杜Vue视频教程,Vue2,Vue3实战精讲,一套通关vue_哔哩哔哩_bilibili
1、vue程序初体验
2、vue核心技术(基础)
3、Vue组件化
前面参见:
vue学习笔记01
vue学习笔记02
vue学习笔记03
vue学习笔记04
vue学习笔记05-CSDN博客
3.13组件自定义事件
1.关于内置事件的实现步骤
第一步:提供事件源(以下这个按钮就是一个事件源)
<button @click="hello">内置事件的实现步骤</button>
第二步:给事件源绑定事件,v-on:事件名 或者 @事件名
第三步:编写回调函数,将回调函数和事件进行绑定
第四步:等待事件的触发,只要事件触发,则执行回调函数
2.关于组件的自定义事件实现步骤:
第一步:提供事件源(这事件源是一个组件)
第二步:给组件绑定事件,v-on:事件名 或者 @事件名
第三步:编写回调函数,将回调函数和事件进行绑定
第四步:等待事件的触发,只要事件触发,则执行回调函数
给User组件绑定一个自定义的事件
<User v-on:even1="doSome"></User>
doSome(){console.log(666)}
#对于组件自定义事件来说,要想让事件发生,需要去执行一段代码。
这个代码负责去触发这个事件,让这个事件发生。
这段代码在哪里写?
$事件绑定在A组件上,则触发这个事件的代码要在A组件当中编写
需要在User组件中写triggerEvent1(){this.$emit('event1')}
触发事件的同时,可以给事件绑定的回调函数传数据
User组件传出:this.$emit('event1',this.name,this.age,this.gender)
父组件接收:doSome(name,age,gender){console.log(name,age,gender)}
另外:可以用es6语法接收:doSome(name,...params){console.log(name,params}
这个params可以看做是一个数组,以数组的形式接收多个参数。
这种方式并没有在子组件中使用:props
所以:子向父传,我们一般使用事件的方式。
3.总结:到目前为止,父子组件之间如何通信
父---子:
props
子---父
第一种方式:在父中定义一个方法,将方法传递给子,然后在子中调用父传过来的方法。这样给父传数据。(这种方式以后很少使用)
第二种方式:使用组件的自定义事件的方式,也可以完成子向父传数据。App组件是父组件,User组件是子组件,子组件向父组件传数据(User给APP组件传数据),在父组件中绑定事件,在子组件中触发事件。父绑定,子触发。(背起来,不用思考)
***前面内容是直接在组件标签上绑定事件,也可以通过写代码的形式实现
<User ref="user"></User>
mounted(){this.$refs.user.$on('event1',this.doSome}}
//给ref="user"的组件绑定event1事件,并且给event1事件绑定一个回调函数:doSome
this.$refs.user.$once('event1',this.doSome)
//事件只触发一次的API
3.14 解绑自定义事件
1、哪个组件绑定的就找哪个组件解绑:
methods:{
this.$off('event1')//这种方式只能解绑一个事件。
this.$off(['event1','event2'])//这种方式解绑多个事件。
this.$off()//解绑所有事件。
}
--其中的this就是VC,就是当前组件,所以解绑的代码要往当前组件里面写:User。
--当VC(当前实例)销毁时,this.$destroy(),解绑了该实例上绑定的所有事件。
2、绑定自定义事件时回调函数的坑
this.$refs.user.$on('event1',this.doSome)
doSome(name,...params){console.log(name,params)}
--这里的回调函数可以有三种写法:a、如上面提前定义好;b、function;c、箭头函数
--如果回调函数是普通函数:函数体当中的this是User组件实例,不是App组件实例。
this.$refs.user.$on('event1',function(){console.log(this)})
因为function是交给this.$refs.user管理的,所以function里面的this就是User组件实例。
--如果回调函数是箭头函数:函数体当中的this是App组件实例。
this.$refs.user.$on('event1',()=>{console.log(this)})
因为箭头函数里面是没有this,它只能往外找,往外就是mouted,而mouted就是当前组件实例的生命周期钩子,所以它里面的this就是App组件实例。
3.15 全局事件总线
非常重要:可以解决所有组件之间的通信
***在前面的父->子的通信过程中,实际上
App.vue中的 this.$refs.user.$on('event1',this.doSome)
和User.vue中的 this.$emit('event1',this.name, this.age, this.gender)红色部分是同一个对象,都是User.vue。
1、全局事件总线原理
2、要实现全局事件总线需要攻克两个问题:
a、这个共享的globalvc对象怎么造出来
b、各个需要通信的组件如何拿到这个共享的globalvc对象
实现步骤
A、在外面创建一个共享的globalvc对象,在main.js中:
//获取VueComponent构造函数
const VueComponentConstructor=Vue.extend({})
//创建一个共享的ve对象
const globalvc = new VueComponentConstructor()
B、回顾一下下面这个图
根据上图的原理,在main.js中:
//给“vue的原型对象”扩展一个x属性,x属性指向了这个共享的vc对象
//给"Vue的原型对象”扩展的这个x属性,其他的组件vc都是可以直接访问到的。
Vue.prototype.x = globalvc
new Vue({el:“#app’,render : h => h(App)
})
C、各个组件就可以获取到这个共享的globalvc对象:如:在App.vue中用this.x即可获得
3、测试代码:
Vip.vue(孙子组件)
<template><div><button @click="triggerEvent">触发事件,发送数据给爷爷</button></div>
</template><script>export default {name : 'vip',data(){return {name : 'jackson'}},methods:{triggerEvent(){//获取共享的vc对象this.x.$emit('eventx', this.name)}},}
</script>
User.vue(父组件)
<template><div><Vip></Vip></div>
</template>
<script>import Vip from './Vip.vue'export default {name : 'User'data(){return {}},components : {vip},methods:{}
</script>
App.vue(爷爷组件)
<template><div><1--准备一个组件--><User></User></div>
</template>
<script>import User from './components/User.vue'export default {name :'App',mounted(){//绑定事件this.x.$on('eventx',this.test)},methods:{test(name){console.log((name)}components :{User}
</script>
4、规范的写法
因为$on,$emit这两个属性vue对象上也有,所以可以在vue创建前(beforeCreate)直接给vue的原型对象扩展一个属性并指向vue对象,该属性有个专有名词:$bus即前面的x。故而在main.js中的代码修改如下:
new Vue({el:“#app’,render : h => h(App),beforeCreate(){//Vue.prototype.x = this//全局事件总线:busVue.prototype.$bus = this}
})
3.16 组件与组件之间的通信总结
组件和组件之间的通信方式,到目前为止我们学习了几个?
1.父向子传数据?
props
2.子向父传数据?
第一种方式:父向子传一个函数,子接收这个函数,然后子去调用这个函数,通过这个函数向父传数据。
第二种方式:组件的自定义事件
绑定事件:负责接收数据
触发事件:负责发送数据
3.可以完成所有组件之间的数据传递,包括:兄弟之间、爷孙之间,但不仅限于这些。
全局事件总线
4.我怎么选择?
父向子:props
子向父:自定义事件
其他关系采用:全局事件总线