全局事件总线(GlobalEvventBus)
一种事件间的通讯方式,适用于任意组件间的通讯(非官方api,是使用中总结出来的组合),需要符合以下两个要求,才能算是全局事件总线
- 确保所有组件都能看到
- 可以调用
$on、$off等方法
安装全局事件总线
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this
},
......
})
使用全局事件总线
- 接收数据:A组件想要接收数据,则在A组件中给$bus绑定自定义事件,事件的回调在A组件自身
methods() {
functionName(data) {......},
mounted() {
this.$bus.$on('自定义事件名称', this.functionName)
},
beforeDestroy() {
this.$bus.$off('自定义事件名称');
}
}
- 提供数据:B组件想要给A组件提供数据,则在B组件中调用
this.$bus.$emit("自定义事件名称", 数据)
销毁
在beforeDestroy钩子中,使用
$off解绑当前自定义事件
main.js
// 引入Vue
import Vue from "vue";
// 引入App组件
import App from "./App"
// 关闭生产提示
Vue.config.productionTip = false
// 创建vm
new Vue({
render: h => h(App),
beforeCreate() {
// 安装全局组件
Vue.prototype.$bus = this
},
}).$mount("#app");
App组件
<template>
<div class="app">
<h1>{{msg}}</h1>
<School />
<Student />
</div>
</template>
<script>
// 引入School组件
import School from './components/School.vue'
import Student from './components/Student.vue'
export default {
name: "App",
// 注册组件
components: {Student, School},
data() {
return {
msg: "你好啊!",
studentName: ''
}
},
}
</script>
<style>
.app {
background-color: gray;
padding: 5px;
}
</style>
School组件
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>地址:{{address}}</h2>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
name: "尚硅谷",
address: "北京·昌平"
}
},
mounted() {
// 绑定自定义事件
this.$bus.$on("hello", (data) => {
console.log("我是School组件,收到了数据", data)
})
},
beforeDestroy() {
// 解绑自定义事件
this.$bus.$off("hello");
},
}
</script>
<style scoped>
.school {
background-color: skyblue;
padding: 5px;
}
</style>
Student组件
<template>
<div class="student">
<h2>姓名:{{name}}</h2>
<h2>性别:{{sex}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="sendStudentName">把学生名给School组件</button>
</div>
</template>
<script>
export default {
name: "Student",
data() {
return {
name: "张三",
sex: "男",
age: 18
}
},
methods: {
sendStudentName() {
this.$bus.$emit("hello", this.name);
}
},
}
</script>
<style scoped>
.student {
background-color: orange;
padding: 5px;
margin-top: 30px;
}
</style>
TodoList 全局事件总线
修改App组件和MyItem组件的通讯
main.is安装事假总线
// 引入Vue
import Vue from "vue";
// 引入App组件
import App from "./App"
// 关闭生产提示
Vue.config.productionTip = false
// 创建vm
new Vue({
render: h => h(App),
beforeCreate() {
// 安装全局事件总线
Vue.prototype.$bus = this
},
mounted() {
/* setTimeout(() => {
this.$destroy();
}, 3000); */
},
}).$mount("#app");
App组件使用数据
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<MyHeader @addTodo="addTodo"/>
<MyList
:todoList="todoList"
/>
<MyFooter
:todoList="todoList"
@checkAllTodo="checkAllTodo"
@deleteAllDoneTodo="deleteAllDoneTodo"
/>
</div>
</div>
</div>
</template>
<script>
import MyHeader from './components/MyHeader'
import MyList from './components/MyList'
import MyFooter from './components/MyFooter'
export default {
name: "App",
// 注册组件
// components: [MyHeader/* , MyList, MyFooter */]
components: {MyHeader, MyList, MyFooter},
data() {
return {
todoList: JSON.parse(localStorage.getItem("todoList")) || []
/* [
{id: '00001', title: "吃饭", done: true},
{id: '00002', title: "打游戏", done: false},
{id: '00003', title: "学习", done: false},
] */
}
},
methods: {
addTodo(todoObj) {
this.todoList.unshift(todoObj);
},
checkTodo(todoId) {
// console.log(todoId)
this.todoList.forEach((todo) => {
if (todo.id === todoId) todo.done = !todo.done;
})
},
deleteTodo (todoId) {
/* this.todoList = this.todoList.filter((todo) => {
return todo.id !== todoId
}) */
this.todoList = this.todoList.filter(todo => todo.id !== todoId)
},
checkAllTodo(done) {
/* this.todoList.forEach((todo) => {
todo.done = done
}); */
this.todoList.forEach(todo => todo.done = done);
},
deleteAllDoneTodo() {
this.todoList = this.todoList.filter(todo => !todo.done);
}
},
watch: {
/* todoList(value) {
localStorage.setItem("todoList", JSON.stringify(value))
} */
todoList: {
deep: true,
handler(value) {
localStorage.setItem("todoList", JSON.stringify(value))
},
}
},
mounted() {
this.$bus.$on('checkTodo', this.checkTodo);
this.$bus.$on('deleteTodo', this.deleteTodo);
},
beforeDestroy() {
this.$bus.$off(['checkTodo', 'deleteTodo']);
},
}
</script>
<style>
/*base*/
body {
background: #fff;
}
.btn {
display: inline-block;
padding: 4px 12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.btn-danger {
color: #fff;
background-color: #da4f49;
border: 1px solid #bd362f;
}
.btn-danger:hover {
color: #fff;
background-color: #bd362f;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
MyItem传递数据
<template>
<li>
<label>
<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
<!-- <input type="checkbox" v-model="todo.done"/> -->
<!-- <input type="checkbox" :checked="todo.done" @click="handleCheck(todo.id)"/> -->
<input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
</li>
</template>
<script scoped>
export default {
name: "MyItem",
// 声明接收传入数据
props: ["todo"],
data() {
return {
}
},
methods: {
handleCheck(todoId) {
// console.log(todoId)
// this.checkTodo(todoId);
// this.$bus.$emit('checkTodo', todoId);
},
handleDelete(todoId) {
if (confirm("确定删除吗?")) {
/* console.log(todoId)
this.deleteTodo(todoId) */
this.$bus.$emit('deleteTodo', todoId);
}
}
},
}
</script>
<style>
/*item*/
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li .btn {
display: none;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover {
background-color: #ddd;
}
li:hover button {
display: block;
}
</style>
本文介绍了如何在Vue应用中使用全局事件总线(GlobalEventBus)来促进组件间的通信,包括安装、使用方法和销毁步骤,以TodoList为例详细展示了其应用过程。
1496

被折叠的 条评论
为什么被折叠?



