Skip to content

EventLoop

EventBus

事件系统是一个典型的发布——订阅模式

实现一个简单的EventBus

DOM事件

参考:DOM编程之事件(二)

事件流

根节点->捕获->事件目标节点->冒泡->根节点

事件委托

事件冒泡模型在为大量单独元素上注册处理程序提供了解决方案(在其公有祖先元素上注册事件,即事件委托)。作用:节省内存,方便管理新增或删除节点时注册事件的逻辑

事件委托就是事件目标不直接处理事件,而是委托其父元素或者祖先元素甚至根元素(document)的事件处理函数进行处理。可以通过事件对象的target属性获得真正触发事件的引用。

事件委托是建立在冒泡模型之上的。

多个事件执行顺序

  • 某些操作会同时出发多个事件,如点击事件执行顺序:touchstart -> touchend -> click
  • 事件执行顺序先捕获后冒泡。addEventListener第三个参数设置为ture时是在捕获阶段执行,而默认是false在冒泡阶段执行。

去抖

函数调用n秒后才会执行,如果函数在n秒内被调用的话则函数不执行,重新计算执行时间

基本思路是采用定时器来实现,在指定时间内连续触发,则清除上一次的定时器,并重新生成新的定时器

js
function debounce(cb, delay) {
    var timer = null
    return function () {
        clearTimeout(timer)
        var args = arguments,
            context = this

        timer = setTimeout(() => {
            cb.apply(context, args)
        }, delay);
    }
}

去抖函数的问题在于:它是在我们事件结束后的一段时间内才会执行,会有一个延迟性。如果函数触发的频率过快,则原本的回调函数一次都不会执行,因为生成的定时器被频繁的清除。不过这也是去抖函数本身的目的,即重新计算执行时间

节流

函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期

基本思路是通过比较时间戳来实现

js
function throttle(cb, duration) {
    var start = new Date()
    return function () {
        var context = this,
            args = arguments,
            now = new Date()

        if (now - start >= duration) {
            cb.apply(context, args);
            start = now;
        }
    }
}

需要注意的是,节流函数和去抖函数本身没有减少事件的触发次数,而是控制事件处理函数的执行来减少实际逻辑处理过程,提高浏览器性能。

Vue事件原理

注册到单个vNode对应的dom实例上

React事件原理

事件委托注册到根节点上面,并且通过合成事件池进行性能优化,在React17版本有调整