389 vue非父子之间通讯 ,事件总线 (event bus),$on注册,开关灯案例
十二、非父子之间通讯 ( 组件 => 组件 ) (重点)
需求 : 组件 jack ===> 恁弄啥哩 ===> 组件 rose
事件总线bus用于管理事件,
vuex用于管理数据状态。
- 是通过
事件总线 (event bus 公交车) 的机制
来实现的 - 事件总线 : 实际上就是一个
空Vue实例
- 可以实现任意两个组件之间的通讯,而不管两个组件到底有什么样的层级关系
- 看图
- 示例 :
// 第一步 : 事件总线
var bus = new Vue()
// 第二步 : 发送数据 可在点击事件里 触发事件
// 参数1 : 唯一标识 参数2:参数
bus.$emit('todo', '恁弄啥哩?')
// 第三步 : 监听事件 接收数据 可在 created 里 注册事件 【也可以在methods里注册事件。】
bus.$on('todo', arg => {
console.log('接收过来的', arg)
})
01-非父子之间的通信.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<!--
需求 : jack 给 rose 发一条消息 : i jump u jump
非父子之间的通信通过 事件总线 (event bus ) 来实现
1. 创建事件总线 (bus) : 一个空的vue实例 const bus = new Vue()
2. 发送数据 触发事件 bus.$emit('jump',XXXX)
3. 接收数据 注册事件 bus.$on('jump,res => { })
-->
<div id="app">
<div>
<div>
<div>
<div>
<jack></jack>
</div>
</div>
</div>
</div>
<div>
<div>
<div>
<rose></rose>
</div>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script>
//1. 事件总线
const bus = new Vue()
// jack
Vue.component('jack', {
template: `<div @click='send'>jack 组件</div>`,
methods: {
send() {
console.log('send');
//2. 发送数据, 触发事件, 发送 一起 jump 的话
// 【代码的执行顺序:先注册,后触发,和传统的DOM操作一样。这个jump事件,只有点击上面的div时,才触发。下面注册的jump,是created阶段就触发。】
bus.$emit('jump', 'i jump u jump')
}
}
})
// rose
Vue.component('rose', {
template: `<div>rose 组件</div>`,
created() {
//3. 接收数据 注册事件 【代码的执行顺序:先注册,后触发,和传统的DOM操作一样。回调函数只有触发jump事件时才会执行。】
console.log('on')
bus.$on('jump', res => {
console.log('rose接收到的:', res)
})
}
})
const vm = new Vue({
el: '#app',
data: {}
})
</script>
</body>
</html>
十三、开关灯案例
02-案例:开关灯(模板).html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
/* 容器 */
.container {
width: 150px;
}
/* 灯 */
.light {
width: 100px;
height: 100px;
border-radius: 50%;
text-align: center;
line-height: 100px;
margin: 0 auto;
color: #fff;
background-color: #000;
}
/* 开灯 */
.turn-on {
background-color: #ff0;
color: #000;
}
/* 灯座 */
.bottom {
width: 150px;
height: 50px;
margin-top: 10px;
line-height: 50px;
text-align: center;
color: #fff;
background-color: #000;
}
</style>
</head>
<body>
<div id="app" class="container">
<light-head></light-head>
<light-bottom></light-bottom>
</div>
<script src="./vue.js"></script>
<script>
//1. 事件总线
const bus = new Vue()
// 创建灯泡组件
Vue.component('light-head', {
// 通过控制台查看,当isLight为true时, div的class同时有 light、turn-on
template: `<div class="light" :class="{ 'turn-on' : isLight }">我是一盏灯</div>`,
data() {
return {
isLight: false
}
},
created() {
//3. 接收数据 注册事件 【也可以在methods里注册事件。】
bus.$on('light', res => {
console.log(res)
this.isLight = res
})
}
})
// 创建灯座组件
Vue.component('light-bottom', {
template: `
<div class="bottom">
<button @click='turnOn'>开</button>
<button @click='turnOff'>关</button>
</div>
`,
methods: {
// 开灯
turnOn() {
// 2. 发送数据 触发事件
bus.$emit('light', true)
},
// 关灯
turnOff() {
//3. 发送数据 触发事件
bus.$emit('light', false)
}
}
})
var vm = new Vue({
el: '#app',
data: {}
})
</script>
</body>
</html>