返回

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

发布时间:2022-12-25 11:03:00 221
# npm# less# 数据# 信息

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) //订阅消息
      }

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),
})

2.2 School.vue

<template>

<div class="school">

<h2 id="h0">学校名称:{{name}}</h2>

<h2 id="h1">学校地址:{{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>


2.3 Student.vue

<template>

<div class="student">

<h2 id="h2">学生姓名:{{name}}</h2>

<h2 id="h3">学生性别:{{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>

 

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>
  •  




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>
 


4、测试结果说明

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

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
SpringBoot和VUE 2022-12-25 10:30:19