• 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 的路由实例和路由信息对象。

    示例:

    created() {
    	this.$watch("searchdata.isasc", this.handleIsAscChange);
    }
    
    • 1
    • 2
    • 3

    逻辑分析

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

    全局挂载

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

    import Vue from 'vue';
    export const bus = new Vue();
    
    • 1
    • 2

    父页面

    父页面 A 中发送事件:

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

    子组件

    监听事件

    在子组件 B 中监听事件:

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    解绑监听事件

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

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

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    QCustomPlot(2)-QCPGraph
    Elasticsearch:什么是检索增强生成 - RAG?
    SpringBoot+Vue项目疫苗预约管理系统
    京东数据分析:2023年9月京东白酒行业品牌销售排行榜
    递归的总结和案例
    Sui Move Object讲解
    【目标检测】【DDPM】DiffusionDet:用于检测的概率扩散模型
    day25--JS进阶(递归函数,深浅拷贝,异常处理,改变this指向,防抖及节流)
    快速入门Docker
    高数_第3章重积分_三重积分的奇偶性
  • 原文地址:https://blog.csdn.net/weixin_42676530/article/details/136829988