父组件 => 子组件
// 父组件
<Child title='I am Child'/>
// 子组件
props: { title: String }
// 父组件
<Child ref='child'/>
...
this.$refs.child.xxx
子组件 => 父组件
// 父组件
<Child @say='handleSay'/>
...
handleSay(val) {
console.log(val) // hello
}
// 子组件
this.$emit('say', 'hello')
兄弟组件
- 通过共同的祖辈组件搭桥,$parent 或 $root
// 兄弟1
this.$parent.$on('say', handleSay)
// 兄弟2
this.$parent.$emit('say', 'hello')
祖先 => 后代
// 祖先
provide() {
return { msg: 'hello world'}
}
// 后代
<span>{{ msg }}</span>
...
inject: ['msg']
// 定义broadcast方法,指定派发事件名称和数据
function broadcast(eventName, data) {
this.$children.forEach(child => {
// 子组件出发$emit
child.$emit(eventName, data)
if(child.$children.length) {
// 递归调用,通过call修改this指向child
broadcast.call(child, eventName, data)
}
}
}
Vue.prototype.$broadcast = function (eventName, data) {
broadcast.call(this, eventName, data)
}
后代 => 祖先
// 定义dispatch方法,指定派发事件名称和数据
function dispatch(eventName, data) {
let parent = this.$parent
// 递归查找父元素
while(parent) {
// 父元素调用$emit出发事件
parent.$emit('say', 'hello')
parent = parent.$parent
}
}
Vue.prototype.$dispatch = dispatch
// Child.vue
<h1 @click='dispatch("say", "hello")'>{{ msg }}</h1>
// App.vue
this.$on('say', this.handleSay)
任意组件间
- 事件总线:创建一个Bus类负责事件派发、监听和回调管理(也可直接创建一个Vue实例,直接使用$on和$emit)
// 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() // 也可用 new Vue()
// 组件1
this.$bus.$on('say', this.handleSay)
// 组件2
this.$bus.$emit('say', 'hello')
-
vuex:创建唯一的全局数据管理者store,通过他管理数据并通知组件状态变更