消息订阅和发布、基础知识和实战应用

1、基础知识

类别引用说明:订阅报纸。用户作为订阅者订购报纸,邮局派送报纸。

1、一种组件间通信的方式,适用于<span style="color:red">任意组件间通信</span>。

2、使用步骤:

安装pubsub:npm i pubsub-js(安装不成功、使用管理员权限运行)

引入: import pubsub from ‘pubsub-js’(订阅和发布都要引入)

3、接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的<span style="color:red">回调留在A组件自身。</span>

methods(){ demo(data){……} } …… mounted() { this.pid = pubsub.subscribe(‘xxx’,this.demo) //订阅消息 }

4、提供数据:pubsub.publish(‘xxx’,数据)(这里的传参传两个、第一个是订阅名、第二个是数据)

5、最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去<span style="color:red">取消订阅。</span>

2、代码实例

实现的效果:student组件中的信息发送到School组件中。student作为信息的发布者,School组件订阅信息。

2.1 main.js//引入Vueimport Vue from ‘vue’//引入Appimport App from ‘./App.vue’//关闭Vue的生产提示Vue.config.productionTip = false//创建vmnew Vue({el:’#app’,render: h => h(App),})

<hr>

2.2 School.vue<template><div class="school"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2></div></template><script>import pubsub from ‘pubsub-js’export default {name:’School’,data() {return {name:’尚硅谷’,address:’北京’,}},mounted() {// console.log(‘School’,this)/* this.$bus.$on(‘hello’,(data)=>{console.log(‘我是School组件,收到了数据’,data)}) */this.pubId = pubsub.subscribe(‘hello’,(msgName,data)=>{console.log(this)// console.log(‘有人发布了hello消息,hello消息的回调执行了’,msgName,data)})},beforeDestroy() {// this.$bus.$off(‘hello’)pubsub.unsubscribe(this.pubId)},}</script><style scoped>.school{background-color: skyblue;padding: 5px;}</style>

<hr>

2.3 Student.vue<template><div class="student"><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2><button @click="sendStudentName">把学生名给School组件</button></div></template><script>import pubsub from ‘pubsub-js’export default {name:’Student’,data() {return {name:’张三’,sex:’男’,}},mounted() {// console.log(‘Student’,this.x)},methods: {sendStudentName(){// this.$bus.$emit(‘hello’,this.name)pubsub.publish(‘hello’,666)}},}</script><style lang="less" scoped>.student{background-color: pink;padding: 5px;margin-top: 30px;}</style>

<hr>

2.4 App.vue<template><div class="app">{{msg}}<School/><Student/></div></template><script>import Student from ‘./components/Student’import School from ‘./components/School’export default {name:’App’,components:{School,Student},data() {return {msg:’你好啊!’,}}}</script><style scoped>.app{background-color: gray;padding: 5px;}</style>3、全局事件总线通信改为消息的订阅和发布3.1 核心部分代码

这里只修改一处、删除列表项的数据方式改为消息订阅和发布的形式

3.1.1 TheItem.vue(样式省略)、发布消息

消息发布、将要删除的id传递给App.vue

<template> <li> <label> <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>import pubsub from ‘pubsub-js’export default { name: "MyItem", //声明接收todo、checkTodo、deleteTodo props: ["todo"], methods: { //勾选or取消勾选 handleCheck(id) { //通知App组件将对应的todo对象的done值取反 // this.checkTodo(id); this.$bus.$emit(‘checkTodo’,id) }, //删除 handleDelete(id) { if (confirm("确定删除吗?")) { //通知App组件将对应的todo对象删除 // this.deleteTodo(id);// this.$bus.$emit(‘deleteTodo’,id)// 消息发布pubsub.publish(‘deleteTodo’,id) } }, },};</script>

<hr>

3.1.2 App.vue 订阅消息<template> <div id="root"> <div class="todo-container"> <div class="todo-wrap"> <TheHeader @addTodo="addTodo" /> <TheList :todos="todos" /> <TheFooter :todos="todos" @checkAllTodo="checkAllTodo" @clearAllTodo="clearAllTodo" /> </div> </div> </div></template><script>import TheHeader from "./components/TheHeader";import TheList from "./components/TheList";import TheFooter from "./components/TheFooter.vue";import pubsub from "pubsub-js";export default { name: "App", components: { TheHeader, TheList, TheFooter }, data() { return { msg: "你好啊!", studentName: "", //由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升) todos: JSON.parse(localStorage.getItem("todos")) || [], // todos: [ // { id: "001", title: "吃饭", done: true }, // { id: "002", title: "睡觉", done: false }, // { id: "003", title: "打豆豆", done: true }, // ], }; }, methods: { //添加一个todo addTodo(todoObj) { this.todos.unshift(todoObj); }, //勾选or取消勾选一个todo checkTodo(id) { this.todos.forEach((todo) => { if (todo.id === id) todo.done = !todo.done; }); }, //删除一个todo deleteTodo(_, id) { this.todos = this.todos.filter((todo) => todo.id !== id); }, //全选or取消全选 checkAllTodo(done) { this.todos.forEach((todo) => { todo.done = done; }); }, //清除所有已经完成的todo clearAllTodo() { this.todos = this.todos.filter((todo) => { return !todo.done; }); }, }, watch: { todos: { deep: true, handler(value) { localStorage.setItem("todos", JSON.stringify(value)); }, }, }, mounted() { this.$bus.$on("checkTodo", this.checkTodo); // this.$bus.$on(‘deleteTodo’,this.checkTodo) //订阅消息、调用方法里边的函数、参数两个。第一个订阅消息名称、第二个是数据。也可以直接写成箭头函数 this.pubId = pubsub.subscribe("deleteTodo", this.deleteTodo); }, beforeDestroy() { this.$bus.$off("checkTodo"); // this.$bus.$off(‘deleteTodo’) // 取消订阅 pubsub.unsubscribe(this.pubId); },};</script>

<hr>

4、测试结果说明

人生就像是一场旅行,遇到的既有感人的,

消息订阅和发布、基础知识和实战应用

相关文章:

你感兴趣的文章:

标签云: