使用场景:
上一篇文章中写到的:
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>