Vue 中使用事件总线来进行组件间通信($emit()、$on() 和 $off())

使用场景:

上一篇文章中写到的:
echarts图表左击显示自定义弹框,右击取消自定义弹框

结构图:(removet修改为remove)

假设这个echarts图表是子组件B页面中。而父页面A的自定义弹框标签里调用了子组件B,(v-if判断)当弹框为true时显示子组件B,反之不显示子组件B(没有dom元素);在子组件B中,需要得知父页面A的弹框是否被关闭,才能将子组件里createElement的弹框元素清除。

所以,通过子组件props获取值且在watch监听父页面A的弹框的状态是行不通的,因为在 Vue 中使用 v-if 来判断是否显示某个元素时,当条件为 false 时,对应的 DOM 元素会被移除,这意味着在页面渲染时,如果 v-if 的条件为 false,相关的 DOM 结构将不会存在于最终的渲染结果中,因此子组件B只能监听到父页面A弹框为显示(true)。

但我们需要的是父页面A弹框为隐藏(false)状态时,移除子组件B中的弹框B。

目录

vue组件通信方法

官网api文档:点击跳转至vue组件事件的中文官网

$emit

$emit(eventName, ...args):用于在当前实例上触发事件。它接收一个事件名称 eventName 作为第一个参数,可以传递额外的参数作为事件回调函数的参数。当调用 $emit() 方法时,会触发相应的事件,并将参数传递给监听该事件的处理函数。

$on

$on(eventName, callback):用于监听当前实例上的事件。当对应的事件被触发时,注册的回调函数 callback 将会被调用。可以通过 $on() 方法来绑定事件监听器。

$off

$off(eventName, callback):用于移除事件监听器。可以通过 off() 方法来解绑先前使用 on() 绑定的事件监听器。如果提供了 eventName 参数,则只会移除该事件相关的监听器;如果同时提供了 eventName 和 callback 参数,则只会移除指定事件及回调函数的监听器。

其它vue方法(本文没使用到的)

$watch():用于侦听 Vue 实例上的数据变化并做出相应的响应。

$nextTick():用于在 DOM 更新之后执行延迟回调函数。

$refs:用于访问子组件或子元素的引用。

this. router 和 this. route:用于访问 Vue Router 的路由实例和路由信息对象。

示例:

javascript 复制代码
created() {
	this.$watch("searchdata.isasc", this.handleIsAscChange);
}

逻辑分析

子组件 B 能够在弹框状态为 false 时也能监听到父页面 A 的弹框关闭状态,这就需要使用事件总线来实现,在 Vue 应用中创建一个事件总线 bus,并在父页面 A 中发送事件,子组件 B 监听这个事件来获取父页面弹框状态的变化。

全局挂载

在 main.js 中创建事件总线 bus:

javascript 复制代码
import Vue from 'vue';
export const bus = new Vue();

父页面

父页面 A 中发送事件:

javascript 复制代码
<template>
  <div class="bigbox-class">
    <el-button type="primary" @click="openClick">显示弹框</el-button>
    <!-- 弹框部分 -->
    <div class="alert-modal-container alertbox" v-if="showModal">
      <div class="alert-modal-shadow"></div>
      <div class="alert-modal-content">
        <div class="alert-modal-header">
          <span>{{ title }}</span>
          <button @click="closeClick">×</button>
        </div>
        <div class="alert-modal-body">
          <line-standard-com></line-standard-com>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import LineStandardCom from "./line-Components/lineCom.vue"; //子组件
import { bus } from './main.js';

export default {
  components: { LineStandardCom },
  data() {
    return {
      showModal: false,
      title: "弹框名称",
    };
  },
  methods: {
    closeClick() {
      this.showModal = false;
      bus.$emit("modalStateChanged", false);
    },
    openClick() {
      this.showModal = true;
      bus.$emit("modalStateChanged", true);
    },
  }
};
</script>

子组件

监听事件

在子组件 B 中监听事件:

javascript 复制代码
<template>
  <div>
    <!-- 子组件的内容,即上篇文章写到的echarts图表创建弹框元素内容 -->
  </div>
</template>

<script>
import "./lineStyle.css";//样式页面
import { bus } from './main.js';

export default {
  created() {
    bus.$on('modalStateChanged', (showModal) => {
      console.log("showModal", showModal);
      if (!showModal) { //父组件A的弹框隐藏(false)时
        console.log('Modal in parent component is closed');
      }
    });
  },
};
</script>

解绑监听事件

上面$on()方法监听方法中输出可以得出,每一次变化弹框状态时,输出showModal次数会递增,意味着会出现内存泄漏或不必要的性能消耗。

所以在每次组件销毁或离开时,建议及时解绑事件监听。可以在子组件的 beforeDestroy 生命周期钩子中,使用 bus. $off 来解绑事件监听,以确保不会产生不必要的内存消耗。

javascript 复制代码
<script>
import { bus } from './main.js';

export default {
  created() {
    bus.$on('modalStateChanged', this.handleModalStateChange);
  },
  beforeDestroy() {
    bus.$off('modalStateChanged', this.handleModalStateChange);
  },
  methods: {
    handleModalStateChange(showModal) {
      if (!showModal) { //父组件A的弹框隐藏(false)时
        if (this.currentMenu && this.currentMenu.parentNode === document.body) {
          document.body.removeChild(this.currentMenu); // 清除子组件B弹框的菜单元素
        }
      }
    },
  }
};
</script>
相关推荐
开开心心就好8 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
Setsuna_F_Seiei10 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲12 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能
默_笙12 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan13 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
kyriewen14 小时前
我扒了 10,221 条 JD:腾讯技术岗 75% 在要 AI
前端·人工智能·ai编程
郑州光合科技余经理14 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
+VX:Fegn089515 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
雪芽蓝域zzs15 小时前
第 7 章:双 Y 轴组合图(柱状 + 折线,看板高频场景)
vue.js·echars
IT_陈寒15 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端