源码分析之Openlayers中的Observable类

访问Openlayers网站(https://jinuss.github.io/Openlayers_map_pages/,网站是基于Vue3 + Openlayers,里面有大量的实践和案例。觉得还不错,可以在这里插入图片描述 给个小星星Star,鼓励一波 https://github.com/Jinuss/OpenlayersMap哦~

概述

本文主要会讲述Observable类以及扩展介绍下event.js中的方法,二者也都和 Openlayers 中的事件机制有关。

源码剖析

Observable

Observable类继承了EventTarget类,是一个抽象类,主要是对外提供注册事件和取消监听的钩子,其实现如下:

class Observable extends EventTarget {
  constructor() {
    super();
    this.on = this.onInternal;
    this.once = this.onceInternal;
    this.un = this.unInternal;
    this.revision_ = 0;
  }
  changed() {
    ++this.revision_;
    this.dispatchEvent(EventType.CHANGE);
  }
  getRevision() {
    return this.revision_;
  }
  onInternal(type, listener) {
    if (Array.isArray(type)) {
      const len = type.length;
      const keys = new Array(len);
      for (let i = 0; i < len; ++i) {
        keys[i] = listen(this, type[i], listener);
      }
      return keys;
    }
    return listen(this, type, listener);
  }
  onceInternal(type, listener) {
    let key;
    if (Array.isArray(type)) {
      const len = type.length;
      key = new Array(len);
      for (let i = 0; i < len; ++i) {
        key[i] = listenOnce(this, type[i], listener);
      }
    } else {
      key = listenOnce(this, type, listener);
    }
    listener.ol_key = key;
    return key;
  }
  unInternal(type, listener) {
    const key = listener.ol_key;
    if (key) {
      unByKey(key);
    } else if (Array.isArray(type)) {
      for (let i = 0, ii = type.length; i < ii; ++i) {
        this.removeEventListener(type[i], listener);
      }
    } else {
      this.removeEventListener(type, listener);
    }
  }
}

function unByKey(key) {
  if (Array.isArray(key)) {
    for (let i = 0, ii = key.length; i < ii; ++i) {
      unlistenByKey(key[i]);
    }
  } else {
    unlistenByKey(key);
  }
}

Observable类中定义的变量和方法如下:

  • revision变量

revision_变量用于记录修订次数,初始值为0;调用changed方法时,revision_会自增1,然后调用this.dispatchEvent方法派生事件;可以通过getRevision方法获取revision_的值。

  • on方法

on方法就是用于注册监听事件。比如mapMap类的实例对象,map.on('pointermove',(evt)=>{})本质上就是调用这个on方法,unonce同理。

on方法接受两个参数,类型type和注册事件listenertype可以是一个字符串也可以是一个数组,如果为数组,则for循环遍历调用listen方法,并将其返回值按顺序包装成一个数组返回;如果时一个字符串,则直接调用listen方法,返回listen方法的结果。

  • once方法

once方法和on方法类似,不过其内部调用的是listenOnce方法,意思就是只监听一次,另外once方法会用注册事件的ol_key属性记录listenOnce方法执行的结果。

  • un方法

un方法会先判断注册事件的ol_key值,该属性可以区分事件注册时调用的是on还是once方法;若key存在,即注册调用了once方法,则会调用unByKey解除监听;否则调用this.removeListener解除。

  • unByKey方法

unByKey不属于Observable类的方法,只是一个工具函数,接收一个key参数;若key是数组,则循环调用unlistenByKey;否则直接调用unlistenByKey解除监听。

event.js

在上面提到的listenlistenOnceunlistenByKey方法都是在event.js中定义的,借此正好介绍下这三个方法

  • listen方法

首先看一下实现,如下:

export function listen(target, type, listener, thisArg, once) {
  if (once) {
    const originalListener = listener;
    listener = function () {
      target.removeEventListener(type, listener);
      originalListener.apply(thisArg ?? this, arguments);
    };
  } else if (thisArg && thisArg !== target) {
    listener = listener.bind(thisArg);
  }
  const eventsKey = {
    target: target,
    type: type,
    listener: listener,
  };
  target.addEventListener(type, listener);
  return eventsKey;
}

Observable类中调用listen方法时,参数传值是listen(this,type,listener),此时this.Argonce都是是undefined,实际上还是调用的this.addEventListener方法,因此在Observable类中取消on方法注册的事件是调用this.removeEventListener就形成闭环了。简单理解,listen方法返回值的key值就是一个包含参数的对象。

  • listenOnce方法

listenOnce方法内部还是调用的listen方法,就是调用listen方法时参数once值为true,此时在listen方法中就会对参数listener进行一层封装,在执行dispatchEvent方法派生该事件时,就会先取消监听,再执行注册事件。

export function listenOnce(target, type, listener, thisArg) {
  return listen(target, type, listener, thisArg, true);
}
  • unlistenByKey方法

unlistenByKey方法实现如下:

export function unlistenByKey(key) {
  if (key && key.target) {
    key.target.removeEventListener(key.type, key.listener);
    clear(key);
  }
}

这个方法之所以存在就是因为listenOnce方法注册组件时,调用addEventListener注册组件注册的是包装后的listener,而该listener是挂载在key.target上。

总结

本文主要讲述了Observable类和event.js中一些方法,Observable类实质上就借助event.js中工具函数对其父类EventTarget中的addEventListenerremoveListener方法的一个应用,方便用户操作调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jinuss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值