Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心基类

    • EventTarget类
    • Observable类
      • 概述
      • 源码剖析
        • Observable类
        • event.js
      • 总结
    • BaseObject类
  • Control控件篇

  • Geom几何图形篇

  • Layer图层篇

  • Renderer篇

  • Feature篇

  • style样式篇

  • 《Openlayers源码》笔记
  • 核心基类
东流
2024-12-03
目录

Observable类

# 概述

本文主要会讲述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);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

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

  • revision变量

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

  • on方法

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

on方法接受两个参数,类型type和注册事件listener。type可以是一个字符串也可以是一个数组,如果为数组,则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

在上面提到的listen、listenOnce和unlistenByKey方法都是在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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在Observable类中调用listen方法时,参数传值是listen(this,type,listener),此时this.Arg、once都是是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);
}
1
2
3
  • unlistenByKey方法

unlistenByKey方法实现如下:

export function unlistenByKey(key) {
  if (key && key.target) {
    key.target.removeEventListener(key.type, key.listener);
    clear(key);
  }
}
1
2
3
4
5
6

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

# 总结

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

编辑 (opens new window)
上次更新: 2024/12/11, 10:30:03
EventTarget类
BaseObject类

← EventTarget类 BaseObject类→

最近更新
01
GeoJSON
05-08
02
Circle
04-15
03
CircleMarker
04-15
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式