当前位置:   article > 正文

Vue 中使用 $on 绑定的事件监听记得移除_vue 清除$on监听

vue 清除$on监听

结论先行

  1. 事件监听,组件注销时记得销毁。
  2. 组件中销毁要指定销毁事件。

说明

  1. 如果组件注销时事件监听没有被销毁,那么之后触发的话依然会执行,可能产生副作用。
  2. 如果没有指定销毁的事件,只用 this.xxx.$off(“emit”) 的话,会移除所有对该事件的监听,如果其他组件(甚至是同一组件,但是放在页面的两个地方)也监听了这个事件,同样会失效。

示例

main.js

const notify = new Vue();
Vue.prototype.notify = notify;
  • 1
  • 2

App.vue


<template>
  <div id="app">
    <CountComponent v-if="show" />
    <CountComponent2 />
    <button @click="click">触发计数</button>
    <button @click="render">注销/重新渲染第一个组件</button>
  </div>
</template>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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;
    },
  },
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

CountComponent.vue


<template>
  <div>count: {{ count }}</div>
</template>

  • 1
  • 2
  • 3
  • 4
  • 5

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++;
    },
  },
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

CountComponent2.vue 复制一份,换一下打印字符串就是。

页面如图:

页面效果

  1. 当 beforeDestroy 中两条 $off 语句都没有执行时,即使注销了第一个组件,点击触发计数按钮,控制台也还是会同时打印两条语句。如果重新渲染第一个组件,打印语句会变成三条……

  2. 如果在第一个组件中解开下列代码:

    // 移除所有监听事件,当本组件被引用多次时,所有引用的监听全部移除
     this.notify.$off("notify");
  • 1
  • 2

注销第一个组件后,点击触发计数按钮毫无反应。重新渲染后点击时,只会触发第一个组件的事件监听函数,打印日志只有一条。

  1. 如果在第一个组件中解开下列代码:
    // 移除指定监听事件
    // this.notify.$off("notify", this.listen);
  • 1
  • 2

就是理想情况:打印语句只有一条,页面上的计数器还是会改变。重新渲染时就会出现两条打印日志。

另外我还注意到,原本是先执行第一个组件的事件监听处理函数,后执行第二个组件的的,如果第一个组件注销又重新渲染,执行会在第二个组件之后。不知道以后会不会踩到这个坑。

点击这里查看示例代码


后记

本质上应该是 this.notify 这个对象一直存在,调用的是它的$on$off方法, 跟页面组件并没有关系。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/222765
推荐阅读
相关标签
  

闽ICP备14008679号