全局事件总线:可以实现任意组件间通信
关于VueComponent:
- school组件 本质是一个名为 VueComponent 的构造函数, 且不是程序员定义的,是 Vue.extend 生成的,即
Vue.extend({ })
的返回值。 - 我们只需要写
<school/>
或<schoo1></school>
,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options )
。 - 特别注意:每次调用 Vue.extend 返回的都是一个全新的 VueComponent。
- 关于this指向:
(1) 组件配置中:data函数、methods 中的函数、watch中的函数、computed中的函数它们的this均是【VueComponent实例对象】。
(2)new Vue(options)
配置中:data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue实例对象】。 - VueComponent 的实例对象,以后简称 vc (也可称之为:组件实例对象)。
Vue 的实例对象,以后简称 vm。
一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法
所以:
main.js
import Vue from 'vue'
import App from './App.vue'
// 所以将x放在Vue的原型对象上,其他组件都可以访问了
Vue.prototype.x = {a:1, b:2}
// 创建vm
new Vue({
el: '#app',
render: h = h(App),
})
School.vue
<script>
export default {
name: 'School',
mounted() {
console.log(this.x) // {a:1, b:2}
}
main.js
import Vue from 'vue'
import App from './App.vue'
// 创建组件
const Demo = Vue.extend({})
// 创建组件的实例对象(即<school/>
const d = new Demo()
Vue.prototype.x = d
// 创建vm
new Vue({
el: '#app',
render: h = h(App),
})
接收数据: School组件想接收数据,则在School组件中给$bus绑定自定义事件,事件的回调留在School组件自身。
School.vue
<script>
export default {
name: 'School',
mounted() {
this.x.$on('hello', (data) => {
console.log('哈哈', data) // 哈哈张三
})
}
}
提供数据: Student组件触发事件
Student.vue
<button @click="sendStudentName">把学生名给School组件</button>
......
export default {
name: 'Student',
data() {
return {
name: '张三',
}
},
methods: {
sendStudentName() {
this.x.$emit('hello',this.name)
}
最终:
安装全局事件总线:
main.js
import Vue from 'vue'
import App from './App.vue'
// 创建vm
new Vue({
el: '#app',
render: h = h(App),
//
beforeCreate() {
// 安装全局事件总线
// Vue.prototype.x = this
// x一般命名为$bus (bus有个翻译是总线的意思)
Vue.prototype.$bus = this
// 在Vue的原型对象上绑定$bus指向vm,this指向vm
})
接收数据: School组件想接收数据,则在School组件中给$bus绑定自定义事件,事件的回调留在School组件自身。
School.vue
<script>
export default {
name: 'School',
mounted() {
// 组件可沿着原型链找到$bus
this.$bus.$on('hello', (data) => {
console.log('哈哈', data) // 哈哈张三
})
}
}
提供数据: 触发事件:
Student.vue
<button @click="sendStudentName">把学生名给School组件</button>
......
export default {
name: 'Student',
data() {
return {
name: '张三',
}
},
methods: {
sendStudentName() {
this.$bus.$emit('hello',this.name)
}
解绑事件: 因为$bus绑定了很多组件的自定义事件,用完自定义事件后如果不解绑,那这个是多余的事件
School.vue
<script>
export default {
name: 'School',
mounted() {
this.$bus.$on('hello', (data) => {
console.log('哈哈', data) // 哈哈张三
})
},
beforeDestroy() {
this.$bus.$off('hello')
}
}