消息的订阅与发布
导入插件
npm i pubsub-js
也可以用其他库
引入
import pubsub from "pubsub-js";
例子
Student组件
<template>
<div class="demo"></div>
</template>
<script>
import pubsub from "pubsub-js";
export default {
name: "StudentList",
methods: {},
mounted() {
//订阅,需要设置一个id,方便取消订阅
this.pubId = pubsub.subscribe("fun", (name, data) => {
console.log("有人执行了fun函数,回调执行了", name, data);
//第三方库的this有可能为undefined,因为不受vue管理,但这里的this因为是箭头函数会向外找this,因此为vc
//或者是将回调函数写在methods中
console.log(this);
});
},
//取消订阅,不用时候执行
beforeDestroy() {
pubsub.unsubscribe(this.pubId);
},
};
</script>
Family组件
<template>
<div class="demo">
<h2>姓名:{{ name }}</h2>
<h2>角色:{{ character }}</h2>
<button @click="sendName">传递数值</button>
</div>
</template>
<script>
import pubsub from "pubsub-js";
export default {
name: "FamilyList",
data() {
return {
name: "野原广志",
character: "father",
};
},
methods: {
//发布
sendName() {
pubsub.publish("fun", "666");
},
},
};
</script>
todolist案例
App组件
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<MyHeader @addTodo="addTodo" />
<MyList :todos="todos" />
<MyFooter
:todos="todos"
@checkAllTodo="checkAllTodo"
@clearAllTodo="clearAllTodo"
/>
</div>
</div>
</div>
</template>
<script>
import MyHeader from "./components/MyHeader";
import MyList from "./components/MyList";
import MyFooter from "./components/MyFooter.vue";
import pubsub from "pubsub-js";
export default {
name: "App",
data() {
return {
// 由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
todos: JSON.parse(localStorage.getItem("todos")) || [],
};
},
methods: {
addTodo(todoObj) {
this.todos.push(todoObj);
},
//注意,由于pubsub接受的数据第一个参数为事件名,因此前面需要填充变量,没用到可以用_
checkTodo(_, id) {
this.todos.forEach((todo) => {
if (todo.id === id) todo.done = !todo.done;
});
},
deleteTodo(_, id) {
if (confirm("确认删除吗?"))
this.todos = this.todos.filter((todo) => todo.id !== id);
},
checkAllTodo(done) {
this.todos.forEach((todo) => {
todo.done = done;
});
},
clearAllTodo() {
this.todos = this.todos.filter((todo) => {
return !todo.done;
});
},
},
watch: {
todos: {
deep: true,
handler(value) {
localStorage.setItem("todos", JSON.stringify(value));
},
},
},
components: { MyHeader, MyList, MyFooter },
mounted() {
this.pubId1 = pubsub.subscribe("checkTodo", this.checkTodo);
this.pubId2 = pubsub.subscribe("deleteTodo", this.deleteTodo);
},
beforeDestroy() {
pubsub.unsubscribe("this.pubId1");
pubsub.unsubscribe("this.pubId2");
},
};
</script>
MyItem组件
<template>
<li>
<label>
<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
<!-- <input type="checkbox" v-model="todo.done"/> -->
<input
type="checkbox"
:checked="inser.done"
@change="handleCheck(inser.id)"
/>
<span>{{ inser.title }}</span>
</label>
<button class="btn btn-danger" @click="handleDelete(inser.id)">删除</button>
</li>
</template>
<script>
import pubsub from "pubsub-js";
export default {
name: "MyItem",
props: ["inser"],
methods: {
handleCheck(id) {
//this.checkTodo(id);
pubsub.publish("checkTodo", id);
},
handleDelete(id) {
//this.deleteTodo(id);
pubsub.publish("deleteTodo", id);
},
},
};
</script>

然而事件检测不到,因此还是全局时间总线好用些。
本文介绍了一个基于pubsub-js库实现的消息订阅与发布机制的例子。通过Student和Family两个组件展示了如何订阅和发布消息,以及在一个todolist应用中如何利用该机制进行组件间的通信。
1790

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



