赞
踩
main.js
const notify = new Vue();
Vue.prototype.notify = notify;
App.vue
<template>
<div id="app">
<CountComponent v-if="show" />
<CountComponent2 />
<button @click="click">触发计数</button>
<button @click="render">注销/重新渲染第一个组件</button>
</div>
</template>
import CountComponent from "./components/CountComponent.vue"; import CountComponent2 from "./components/CountComponent2.vue"; export default { name: "App", components: { CountComponent, CountComponent2 }, data() { return { show: true }; }, methods: { click() { this.notify.$emit("notify"); }, render() { this.show = !this.show; }, }, };
CountComponent.vue
<template>
<div>count: {{ count }}</div>
</template>
export default { data() { return { count: 0 }; }, mounted() { console.log("count component mounted"); this.notify.$on("notify", this.listen); }, beforeDestroy() { console.log("count component beforeDestroy"); // 移除所有监听事件,当本组件被引用多次时,所有引用的监听全部移除 // this.notify.$off("notify"); // 移除指定监听事件 // this.notify.$off("notify", this.listen); }, methods: { listen() { console.log("count component listen"); this.count++; }, }, };
CountComponent2.vue 复制一份,换一下打印字符串就是。
页面如图:
当 beforeDestroy 中两条 $off 语句都没有执行时,即使注销了第一个组件,点击触发计数按钮,控制台也还是会同时打印两条语句。如果重新渲染第一个组件,打印语句会变成三条……
如果在第一个组件中解开下列代码:
// 移除所有监听事件,当本组件被引用多次时,所有引用的监听全部移除
this.notify.$off("notify");
注销第一个组件后,点击触发计数按钮毫无反应。重新渲染后点击时,只会触发第一个组件的事件监听函数,打印日志只有一条。
// 移除指定监听事件
// this.notify.$off("notify", this.listen);
就是理想情况:打印语句只有一条,页面上的计数器还是会改变。重新渲染时就会出现两条打印日志。
另外我还注意到,原本是先执行第一个组件的事件监听处理函数,后执行第二个组件的的,如果第一个组件注销又重新渲染,执行会在第二个组件之后。不知道以后会不会踩到这个坑。
本质上应该是 this.notify 这个对象一直存在,调用的是它的$on
和$off
方法, 跟页面组件并没有关系。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。