怎样理解js中的事件监听

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样理解js中的事件监听相关的知识,希望对你有一定的参考价值。

js的监听事件就是相当于注册一个监听器,随时检测对应事件有没有发生,如果发生了自动调用定义好的函数来处理。

一般情况下 监听事件是对应于dom元素而言的,同时也需要声明所监听事件种类。
比如可以为一个按钮设置监听事件,点击之后自动调用相应函数处理。
同时可以在用函数处理时使用事件对象(event object)来获得关于触发这个事件的对象的信息。
参考技术A js的监听事件就是相当于注册一个监听器,随时检测对应事件有没有发生,如果发生了自动调用定义好的函数来处理。
一般情况下 监听事件是对应于dom元素而言的,同时也需要声明所监听事件种类。
比如可以为一个按钮设置监听事件,点击之后自动调用相应函数处理。
同时可以在用函数处理时使用事件对象(event object)来获得关于触发这个事件的对象的信息。

简单剖析Node中的事件监听机制

使用js的class类简单的实现一个事件监听机制,不同于浏览器中的时间绑定与监听,类似于node中的时间监听,并且会在接下来的文章中去根据自己的理解去写一下Event模块中的原理。

Node.js使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效。并且Node中的大量模块都使用了Event机制,因此可以说是整个Node中最重要的模块之一。

实例:

    let event = new eventEmitter();
    event.on('someType',function(){
        
    });
    event.emit('someType');

依据上述例子,手动触发一个类型的事件,调用监听的回调函数,可以先来实现一个最为简单的小例子,例如下放代码:

class eventEmitter {
    constructor() {
        this.callEvent = '';
    }
    on(eventType, callback) {
        this.callEvent = callback;
    };
    emit(eventType) {
        this.callEvent();
    };
}
let event = new eventEmitter();
event.on('click', function () {
    console.log('click')
});
event.emit('click');

上述实现的代码,能够简单的实现,当我们执行emit()方法时,去执行原本on()中传入的回调函数。
我们知道node中的Event模块是一个简单的事件监听模式的实现。Event模块中只提供了一个对象EventEmitter,EventEmitter的核心就是事件监听与事件触发的监听功能的封装。

EventEmitter可以让我们注册一个或者多个函数作为listeners,在特定的事件触发时被调用。我们去监听的函数就是listeners。当然,我们可以注册多个监听事件,所以需要一个map结构来存储监听事件和回调函数的对应关系。

在EventEmitter类中,已键值对的方式来存储事件名和对应的监听器。

首先根据上边的类来实现我们on事件,先来个events来作为存储的键值对,每次传入的值为事件类型和回调函数,代码简单如下:

    EventEmitter.prototype.on = function on(type,listener){
    return _on(this,type,listener);
};

function _on(target,type,listener){
    var m;
    var events;
    var existing;
    if(typeof listener !== 'function'){
        throw new Error("监听者必须是一个函数");
    }
    //获取到对象上的监听事件键值对
    events = target._events;
    if(!events){
        //如果没有键值对,则重新自定义
        events = target._events = {};
        target._eventsCount = 0;
    }else{
        //获取原来键值对中的listener事件
        existing = events[type];
    }

    if(!existing) {
        //如果原本的事件监听的键值对中没有该type的该监听事件
        //则在events中存放该type和该监听事件的键值对
        existing = events[type] = listener;
        //并且当前内存中存放的监听事件加1
        ++target._eventsCount;
    }

    return target;
}

现在on事件可以使用了,我们先不去思考最大监听数的限制还有键值对的初始化不正确等其他因素,这些可以放在之后进行优化,接下来简单的去实现EventEmitter中的emit事件

EventEmitter.prototype.emit = function emit(type){
    return _emit(this,type);
};

function _emit(target,type){
    var events,exiting,handler;
    if(!type){
        throw new Error('触发的事件不能为空');
    }
    //获取到对象上的监听事件键值对
    events = target._events;
    //根据type获取到监听事件
    handler = events[type];
    if(!handler){
        return false;
    }
    handler();
}

同样的emit事件的实现是简单的从键值对中根据type获取到监听事件去执行。这里还没有考虑传入多个参数的情况。

根据上边的简单实现,我们可以来进行下尝试,比之前的版本相比,我们可以监听多个事件,去触发多个回调函数了。

event.on('click', function () {
    console.log('click')
});

event.on('click1',function (){
    console.log('click11');
});

event.emit('click');
//输出click

event.emit('click1');
//输出click11

console.log(event._events);
//输入{click: [Function],click1:[Function]}

这里简单的实现了多个事件注册,多个事件触发的EventEmitter,接下来会继续进行设置监听个数、以及触发时传入多个参数的剖析。

参考:[https://github.com/nodejs/node/blob/v6.0.0/lib/events.js]

以上是关于怎样理解js中的事件监听的主要内容,如果未能解决你的问题,请参考以下文章

在android中怎样给整个页面设置监听事件

浅谈js事件监听

jQuery是怎样监听到事件的?

vue.js怎样移除绑定的点击事件

如何用js监听滚动条滚动事件

如何用js监听滚动条滚动事件?