最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

JavaScript EventEmitter 背后的秘密 完整版

来源:懂视网 责编:小采 时间:2020-11-27 22:17:19
文档

JavaScript EventEmitter 背后的秘密 完整版

JavaScript EventEmitter 背后的秘密 完整版:什么是 Event Emitter? Event emitter 听起来只是触发一个事件,这个事件任何东西都能监听。 想象一下这样的场景,在你的异步代码中,去呼叫一些事件的发生,以及让你其他部分都要听到你的呼叫并且注册他们的想法。 为了不同的目的,对于 Ev
推荐度:
导读JavaScript EventEmitter 背后的秘密 完整版:什么是 Event Emitter? Event emitter 听起来只是触发一个事件,这个事件任何东西都能监听。 想象一下这样的场景,在你的异步代码中,去呼叫一些事件的发生,以及让你其他部分都要听到你的呼叫并且注册他们的想法。 为了不同的目的,对于 Ev

什么是 Event Emitter?

Event emitter 听起来只是触发一个事件,这个事件任何东西都能监听。

想象一下这样的场景,在你的异步代码中,去“呼叫”一些事件的发生,以及让你其他部分都要听到你的“呼叫”并且注册他们的想法。

为了不同的目的,对于 Event Emitter 模式有大量不同的实现,但是基本的想法是为了给一个框架提供事件的管理以及能够去订阅他们。

在这里,我们的目标创建属于我们自己的 Event Emitter 去理解背后的秘密。所以,让我们看一下下面的代码是怎么工作的。

let input = document.querySelector("input[type="text"]");
let button = document.querySelector("button");
let h1 = document.querySelector("h1");

button.addEventListener("click", () => {
 emitter.emit("event:name-changed", { name: input.value });
});

let emitter = new EventEmitter();
emitter.subscribe("event:name-changed", data => {
 h1.innerHTML = `Your name is: ${data.name}`;
});

让我们开始。

class EventEmitter {
 constructor() {
 this.events = {};
 }
}

我们先创建一个 EventEmiiter 类以及初始化 events 空对象属性。这个 events 属性的目的是为了存储我们的事件集合,这个 events 对象使用事件名当做 key,用订阅者集合当做 value。(可以把每个订阅者看作是一个函数)。

订阅函数

subscribe(eventName, fn) {
 if (!this.events[eventName]) {
 this.events[eventName] = [];
 }

 this.events[eventName].push(fn);
}

这个订阅函数获取事件名称,在我们之前的例子中,它是 "event:name-changed" 以及传入一个回调,当有人调用 emit(或尖叫)事件的时候调用回调。

在 JavaScript 函数的优点之一是函数是第一对象,所以我们能像之前我们的订阅方法一样,通过函数作为另一个函数的参数。

如果未注册这个事件,我们需要在第一次为它设置一个初始值,事件名称作为 key 以及初始化一个空数组赋值给它,然后我们将函数放入这个数组,以便我们想通过 emit 去调用这个事件。

调用函数

emit(eventName, data) {
 const event = this.events[eventName];
 if (event) {
 event.forEach(fn => {
 fn.call(null, data);
 });
 }
}

这个调用函数接受事件名,这个事件名是我们想“呼叫”的名称,以及我们想传递给这个事件的数据。如果在我们的 events 中存在这个事件,我们将带上数据循环调用所有订阅的方法。

使用上面的代码能做我们所说的全部的事情。但我们仍然有一个问题。当我们不再需要它们的时候,我们需要一种方法来取消注册这些订阅,因为如果你不这样做,将造成内存泄漏。

让我们来解决这个问题,通过在订阅函数中返回一个取消注册的方法。

subscribe(eventName, fn) {
 if (!this.events[eventName]) {
 this.events[eventName] = [];
 }

 this.events[eventName].push(fn);

 return () => {
 this.events[eventName] = this.events[eventName].filter(eventFn => fn !== eventFn);
 }
}

因为 JavaScript 函数是第一对象,你能在一个函数中返回一个函数。因此现在我们能调用这个取消注册函数,如下:

let unsubscribe = emitter.subscribe("event:name-changed", data => console.log(data));

unsubscribe();

当我们调用取消注册函数的时候,我们删除的功能依赖于对订阅函数集合的筛选方法(Array filter)。

和内存泄露说再见!👋👋

你能运行这份代码,所有代码都在这里。

html代码

<!DOCTYPE html>
<html>
<head>
	<script src="script.js"></script>
</head>
<body>
	<input type="text">
	<h1></h1>
	<button>Change name</button>
</body>
</html>

js代码

class EventEmitter {
 constructor() {
 this.events = {};
 }

 emit(eventName, data) {
 const event = this.events[eventName];
 if (event) {
 event.forEach(fn => {
 fn.call(null, data);
 });
 }
 }

 subscribe(eventName, fn) {
 if (!this.events[eventName]) {
 this.events[eventName] = [];
 }

 this.events[eventName].push(fn);
 return () => {
 this.events[eventName] = this.events[eventName].filter(eventFn => fn !== eventFn);
 }
 }


}

document.addEventListener("DOMContentLoaded", function (event) {
 let input = document.querySelector('input[type="text"]');
 let button = document.querySelector('button');
 let h1 = document.querySelector('h1');

 button.addEventListener('click', () => {
 emitter.emit('event:name-changed', { name: input.value });
 });

 let emitter = new EventEmitter();
 emitter.subscribe('event:name-changed', data => {
 h1.innerHTML = `Your name is: ${data.name}`;
 });
});

注:这份代码可能需要翻墙或者特别慢,所以我放到了 脚本之家 上,大家可以下载EventEmitter-jb51.rar。

原文出自:https://medium.com/@NetanelBasal/javascript-the-magic-behind-event-emitter-cce3abcbcef9#.nzgbagnxe

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

JavaScript EventEmitter 背后的秘密 完整版

JavaScript EventEmitter 背后的秘密 完整版:什么是 Event Emitter? Event emitter 听起来只是触发一个事件,这个事件任何东西都能监听。 想象一下这样的场景,在你的异步代码中,去呼叫一些事件的发生,以及让你其他部分都要听到你的呼叫并且注册他们的想法。 为了不同的目的,对于 Ev
推荐度:
标签: 完整版 js event
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top