• Vue学习之--------消息订阅和发布、基础知识和实战应用(2022/8/24)


    1、基础知识

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

    1、一种组件间通信的方式,适用于任意组件间通信。

    2、使用步骤:

    1. 安装pubsub:npm i pubsub-js(安装不成功、使用管理员权限运行)
      在这里插入图片描述

    2. 引入: import pubsub from 'pubsub-js'(订阅和发布都要引入)
      3.

    3、接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

          methods(){
            demo(data){......}
          }
          ......
          mounted() {
            this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    5、最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

    2、代码实例

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

    2.1 main.js

    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    
    //创建vm
    new Vue({
    	el:'#app',
    	render: h => h(App),
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.4 App.vue

    <template>
    	<div class="app">
    		<h1>{{msg}}</h1>
    		<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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3、全局事件总线通信改为消息的订阅和发布

    全局事件总线实现组件间通信:https://blog.csdn.net/weixin_43304253/article/details/126475369

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    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>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    4、测试结果说明

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    基于4G/5G协同的高密重载场景网络规划方法
    2022年11月19日(星期六):骑行甸尾
    常见聚类算法及使用--均衡的迭代并减少聚类中心的层次聚类(BIRCH)
    第8章 Spring(二)
    浮动元素的特点(2)
    MongoDB是什么?非关系型数据库的优点?安装使用教程
    Spring Boot 加载本地 JAR 包的技术实践
    3.6 样式绑定
    Java基本数据类型包装类的高速缓冲区
    snownlp情感分析
  • 原文地址:https://blog.csdn.net/weixin_43304253/article/details/126514030