V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
banxi1988
V2EX  ›  前端开发

vue-geventbus - 一个优雅的 Vue 全局事件处理插件

  •  
  •   banxi1988 ·
    banxi1988 · 2018-08-11 22:08:49 +08:00 · 2293 次点击
    这是一个创建于 2078 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Vue 中全局事件处理的传统做法

    1. 先创建一个名为 eventBus 的全局 Vue 实例。
    const eventBus = new Vue();
    export default eventBus;
    
    1. 在 Vue 组件中使用时,一般在 mounted 生命周期中注册事件处理函数。在 destroyed 生命周期函数中解除注册的事件以免造成内存泄漏。
    import { Component, Prop, Vue } from "vue-property-decorator";
    import eventBus from "@/services/eventBus";
    
    @Component
    export default class HelloWorld extends Vue {
     
      mounted(){
          eventBus.$on(AppEvents.userInfoDidChanged, this.onUserInfoChanged);
      }
      
      onUserInfoChanged(){
          
      }
      
      destroyed(){
          eventBus.$off(AppEvents.userInfoDidChanged, this.onUserInfoChanged);
      }
    }
    

    这样使用起来颇为繁琐。注册了某一个事件之后,必须在适用的时候取消注册。

    使用 vue-geventbus 之后

    这里要介绍的 Vue 插件 vue-geventbus 可以帮我们优雅的解决此问题。 在使用了 vue-geventbus 之后。后面我们写全局事件的注册函数就可以像下面这样写了。

    this.$gon(AppEvents.userInfoDidChanged, () => {
        
    });
    

    vue-geventbus 插件会在此 Vue 实例销毁时自动将此实例注册的全局事件处理函数全部清理以避免内存泄漏。 注意这里使用的是 vue-geventbus 插件添加的扩展方法 $gon$on 多了一个 g,就像 LOVE 去掉一半变 LOLI (这都啥跟啥啊?)

    原理

    具体来说是通过 Vue 的 Mixin 机制,为 Vue 组件添加了如下 mixin

        vueClass.mixin({
          destroyed() {
            const vue = this as any;
            clazz.removeListenersByVue(vue);
          }
        });
    

    也就是在 Vue 组件实例销毁时将此组件注册的所有事件处理函数清理掉。 后面的整个插件的代码都是为了实现此逻辑而来的。

    事实上 vue-geventbus 重新实现了基本的 Vue 事件处理逻辑。下面的两者的事件对照表,也就是说 vue-geventbus 提供了 Vue 事件处理函数的全局事件处理函数的版本。

    • $on -> $gon
    • $once -> $gonce
    • $emit -> $gemit
    • $off -> $goff

    本插件测试完善,也可以通过测试代码更多了了解本插件的一些特性细节。详情见参考仓库中的源代码。

    3 条回复    2018-08-12 09:07:12 +08:00
    leekafai
        1
    leekafai  
       2018-08-11 22:26:55 +08:00 via Android
    老哥,地址
    banxi1988
        2
    banxi1988  
    OP
       2018-08-11 22:43:47 +08:00   ❤️ 1
    @leekafai #1
    哈哈,我隐藏在其中一句介绍的话中。
    > 这里要介绍的 Vue 插件 vue-geventbus 可以帮我们优雅的解决此问题。
    其中的 `vue-geventbus` 是包含链接的。

    https://github.com/banxi1988/vue-geventbus
    leekafai
        3
    leekafai  
       2018-08-12 09:07:12 +08:00 via Android
    @banxi1988 (⁄ ⁄•⁄ω⁄•⁄ ⁄)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2946 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:03 · PVG 17:03 · LAX 02:03 · JFK 05:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.