Vue 源码学习 --事件 event

1. 事件概述

Vue 中的事件可以分为 2 类:原生 DOM 事件、自定义事件。两者在使用方式、用途、源码处理的实现上存在区别。

使用方式:
原生 DOM 事件可用在原生 DOM 元素上,也可用在组件上(这种情况下,需使用 .native 修饰符);自定义事件只能在组件上使用。
用途:
它们都具有事件的基本用途 – 界面与用户交互;而自定义事件还经常用于父子组件之间的通信
源码实现:
原生 DOM 事件的处理主要依靠原生的 addEventListenerremoveEventListener 来完成;而自定义事件则是通过事件中心的模型处理的。

2. 代码实现基本事件中心

Vue 中的事件处理,主要有 vm.$on、vm.$off、vm.$emit、vm.$once 这四个方法:

vm.$on:
监听当前实例上的自定义事件。

vm.$off:
移除自定义事件监听器。
如果没有提供参数,则移除所有的事件监听器;
如果只提供了事件,则移除该事件所有的监听器;
如果同时提供了事件与回调,则只移除这个回调的监听器。

vm.$emit:
触发当前实例上的事件。附加参数都会传给监听器回调。

vm.$once:
监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。

下面是实现基础功能的代码部分:

class EventBus {
        constructor() {
          // 事件中心的核心
          // 存储所有的事件名称以及对应的事件处理函数列表
          this._events = {};
        }

        // vm.$on(event, callback)
        // 根据事件名称 event,将事件回调放进对应的列表 
        on(event, callback) {
          (this._events[event] || (this._events[event] = [])).push(callback);
        }

        // vm.$off([event, callback])
        off() {
          let _args = [...arguments];
          let length = _args.length;
          switch (length) {
            case 0: // 移除所有的事件的回调函数
              for (let event in this._events) {
                this._events[event] = [];
              }
              break;
            case 1: // 移除特定事件的事件回调列表
              let _event0 = _args[0];
              for (let event in this._events) {
                if (_event0 === event) {
                  this._events[event] = [];
                }
              }
              break;
            default: // 移除指定特定事件下的特定的事件回调
              let _event = _args[0];
              let _callback = _args[1];
              for (let event in this._events) {
                if (_event === event) {
                  this._events[event].map((item, index) => {
                    if (item.toString() === _callback.toString()) {
                      this._events[event].splice(index, 1);
                    }
                  });
                }
              }
          }
        }

        // vm.$emit(eventName, [...args])
        // 找到指定事件名称的回调函数列表,遍历且执行回调
        emit(eventName) {
          let callbacks = this._events[eventName];
          let params = [...arguments].slice(1);
          callbacks &&
            callbacks.map((_callback) => {
              _callback(...params);
            });
        }

        // vm.$once(event, callback)
        // 根据事件名称 event,将事件回调放进对应的列表;且该回调被执行一次后,就会移除
        once(event, callback) {
		  let that = this
          function _on() {
           // 移除事件处理回调函数
            that.off(event, _on);
            // 使用参数,调用回调
            callback.apply(that, arguments);
          }
		  that.on(event, _on);
        }
      }

接下来,创建出 EventBus 实例后,就可以使用功能了,下面是一些简单的测试:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值