Vue--消息的订阅与发布

本文介绍了一个基于pubsub-js库实现的消息订阅与发布机制的例子。通过Student和Family两个组件展示了如何订阅和发布消息,以及在一个todolist应用中如何利用该机制进行组件间的通信。
摘要由CSDN通过智能技术生成

消息的订阅与发布

导入插件

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>

请添加图片描述

然而事件检测不到,因此还是全局时间总线好用些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值