Vue--全局事件总线

全局事件总线

案例

请添加图片描述
根据图中的信息:需要接收的组件绑定事件,并且执行回调函数,而发送信息的组件,控制事件发生以及将信息发送到对应组件

Student组件,接收信息

<template>
  <div class="demo"></div>
</template>

<script>
export default {
  name: "StudentList",
  methods: {},
  mounted() {
    this.$bus.$on("send", (data) => {
    //接收信息,并打印输出
      console.log("兄弟组件收到信息", data);
    });
  },
  beforeDestroy() {
  //每次销毁前都将事件解绑,不占用事件名
    this.$bus.$off("send");
  },
};
</script>

Family组件,发送信息

<template>
  <div class="demo">
    <h2>姓名:{{ name }}</h2>
    <h2>角色:{{ character }}</h2>
    <button @click="sendName">传递数值</button>
  </div>
</template>

<script>
export default {
  name: "FamilyList",
  data() {
    return {
      name: "野原广志",
      character: "father",
    };
  },
  methods: {
    sendName() {
    //事件触发,传递信息
      this.$bus.$emit("send", this.name);
    },
  },
};
</script>

需要在main.js内配置相应的$bus

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  beforeCreate() {
    // 在Vue的原型对象上添加个$bus
    Vue.prototype.$bus = this
  }
}).$mount('#app')

todolist修改

与案例中的类似,修改为用事先定义的$bus即可,这里关系为,App的孙子组件为MyItem,实现两者的通信,则需要利用$bus

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>
export default {
  name: "MyItem",
  props: ["inser"],
  methods: {
    handleCheck(id) {
      this.$bus.$emit("checkTodo", id);
    },
    handleDelete(id) {
      this.$bus.$emit("deleteTodo", id);
    },
  },
};
</script>

App

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <MyHeader @addTodo="addTodo" />
        <MyList
          :todos="todos"
          :checkTodo="checkTodo"
          :deleteTodo="deleteTodo"
        />
        <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";

export default {
  name: "App",
  data() {
    return {
      // 由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
      todos: JSON.parse(localStorage.getItem("todos")) || [],
    };
  },
  methods: {
    addTodo(todoObj) {
      this.todos.push(todoObj);
    },
    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;
      });
    },
  },
  mounted() {
    this.$bus.$on("checkTodo", this.checkTodo);
    this.$bus.$on("deleteTodo", this.deleteTodo);
  },
  watch: {
    todos: {
      deep: true,
      handler(value) {
        localStorage.setItem("todos", JSON.stringify(value));
      },
    },
  },
  components: { MyHeader, MyList, MyFooter },
};
</script>

运行结果
在这里插入图片描述
其中by root的就是通过总线来实现通信的,而其他则表示用的是其他方法。
如果是父传子则用props比较方便,子传父也有之前提及的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值