JavaScript系列 事宜

一步,一步前进の一步

《JavaScript系列 事宜》

事宜是文档或许浏览器窗口中发作的一些交互霎时。JS注册事宜处置惩罚递次来预订事宜,当事宜发作的霎时来实行响应的代码,进而完成 JS 和 HTML(即文档或许浏览器窗口) 的交互。

事宜流

事宜流形貌的是从页面中吸收事宜的递次。
《JavaScript系列 事宜》

用手指戳一下屏幕上的同心圆的中间,先点到的是最外围的大圆,照样最中心的小圆呢?这个就是事宜流要处置惩罚的实质题目。夙兴的 IE 和 Netscape 对此有差别的看法,IE以为先点到的是最小的圆,然后在一层层的通报到最表面的大圆(事宜冒泡),Netscape 恰好相反,最早遇到的是最外围的大圆,然后在一层层的追踪到最精准的小圆(事宜捕捉)。

事宜冒泡:事宜最先由最详细的元素吸收,然后逐级向上流传到较为不详细的节点。

事宜捕捉:事宜是从不太详细的节点最先发生吸收,而最详细的节点应该是末了吸收事宜的。

事宜流范例出来讲,事宜通报有三个阶段: 捕捉阶段、目标阶段、冒泡阶段。
《JavaScript系列 事宜》

事宜处置惩罚递次

浏览器的事宜处置惩罚也许就是注册、监听。递次最先就对将来会发作的某些事变,做出预期,对预期做出准确的回响反映。事宜处置惩罚递次就是被注册准确回响反映监听这个操纵由浏览器本身完成。
浏览器供应了三种要领,为事宜绑定监听函数。

html 属性体式格局

<div onclick="doSomething()">

须要注重的是:此处的事宜处置惩罚递次是须要带小括号的,也许的历程是当 div 吸收到事宜时,会将onclick背面的代码一成不变的传入JavaScript引擎实行,不加小括号就不会触发处置惩罚递次。

此体式格局会让 js 的代码和 html 代码杂糅在一起,不容易代码的变动和保护,因而不引荐运用。

Dom 0级事宜注册

div.onclick = function (event) {
  console.log('触发事宜');
};

以元素节点对象的事宜属性的体式格局举行注册,与第一种体式格局相似。
该事宜只会在冒泡阶段触发。

Dom 2级事宜注册

target.addEventListener(type, listener[, useCapture])
type事宜称号,大小写敏感;listener处置惩罚函数;useCapture是不是在捕捉阶段触发。
引荐运用该体式格局举行事宜的注册,能够对一致节点注册多个事宜处置惩罚函数。当前冒泡流是被大多浏览器支撑,因而useCapture大多赋为false。

document.addEventListener('click', hello, false);
document.addEventListener('click', hello2, false);

IE 事宜处置惩罚递次

初期的 IE 浏览器只支撑冒泡流,有本身的事宜注册和移除的要领:attachEvent()detachEvent()

btn.attachEvent('onclick', function () {
    alert('ie browser');
});

须要注重的是处置惩罚函数的 this 是指向 window 的,而不像前两种事宜处置惩罚函数的 this 会指向事宜地点的 dom 节点对象。

跨浏览器事宜处置惩罚递次

红宝书计划代码以下:

var EventUtil = {
    addHandler: function(elm, type, handler) {
        if (elm.addEventListener) {
            elm.addEventListener(type, handler, false);
        } else if (elm.attachEvent) {
            elm.attachEvent('on' + type, handler);
        } else {
            elm['on' + type] = handler;
        }
    }
};

该要领是比较好的,然则处置惩罚函数实行时的 this 指向照样有一点点题目,attachEvent体式格局照样指向 window 的,假如想越发完美,请参考 js 忍者秘笈上面的计划。

在处置惩罚事宜时,我们须要斟酌一些机能的题目,有必要限定事宜处置惩罚函数的数目,恰当的时刻将已有的事宜处置惩罚递次移撤除或许采纳事宜托付机制削减注册的个数。下面我们简朴谈谈怎样移除事宜处置惩罚递次。

var EventUtil = {
    removeHandler: function (elm, type, handler) {
        if (elm.removeEventListener) {
            elm.removeEventListener(type, handler, false);
        } else if (elm.detachEvent) {
            elm.detachEvent('on' + type, handle);
        } else {
            elm['on' + type] = handler;
        }
    }
}

事宜的移除有个准绳,怎样注册的就要一成不变的 copy 参数挪用移除。此处须要注重的是当你的事宜处置惩罚函数是匿名函数时,那将会永久也清算不掉了。

this 指向

处置惩罚函数实行时,this 指向当代的浏览器指向的是 事宜地点dom 节点,老 IE 指向window。

事宜对象

事宜发作后,会发生一个事宜对象,作为参数传给监听函数。事宜有多少的实例属性和实例要领。只讲下笔者以为主要的currentTargettargetpreventDefault().stopPropagation()stopImmediatePropagation()

currentTarget事宜处置惩罚函数注册在什么节点上,那末 currentTarget 就永久的指向了该节点。
target,我们回忆一下事宜流的观点,事宜会阅历捕捉阶段、目标阶段、冒泡阶段,能够感觉到事宜的通报画了个对称的钩,target 示意事宜当前所处的节点位置。
我们不仅能够读取事宜的状况,还能够工资的转变它的内部状况。

preventDefault()阻挠事宜的默许行动,如 a 标签被点击时就会跳转到新的 url,我们能够运用event.preventDefault()来阻挠跳转。

stopPropagation()阻断事宜的冒泡流或许事宜捕捉流。但假如一致节点上注册了多个事宜处置惩罚递次,那末该节点上的事宜处置惩罚递次会继承处置惩罚,它只会阻断事宜向上或向下的流传。

stopImmediatePropagation()更加恶毒,事宜会住手在该事宜处置惩罚递次上,同节点的其他事宜处置惩罚递次也不会被触发了。

事宜代办

因为事宜会在冒泡阶段向上流传到父节点,因而能够把子节点的监听函数定义在父节点上,由父节点的监听函数一致处置惩罚多个子元素的事宜。这类要领叫做事宜的代办(delegation)。

<ul>
    <li>test</li>
    <li>test</li>
    <li>test</li>
    <li>test</li>
    <li>test</li>
    ...
</ul>

假定营业须要给 li 增加 click 监听事宜,那末初学者可能会采纳直接猎取 li 节点的体式格局举行事宜递次的绑定,那末有几个 li,就须要注册多少个事宜处置惩罚递次。能够采纳事宜代办机制完成机能优化,代码以下:

var ul = document.querySelector('ul');

ul.addEventListener('click', function (event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    // some code
  }
});

事宜代办和事宜托付是一致个东西,主如果运用事宜冒泡和事宜的实例属性 target,目标是削减事宜处置惩罚递次的数目,进步机能。

材料引荐

红宝书
阮一峰 事宜模子
🌚 前端进修QQ群: 538631558 🌚

【开辟环境引荐】
Cloud Studio 是基于浏览器的集成式开辟环境,支撑绝大部分编程言语,包含 HTML5、PHP、Python、Java、Ruby、C/C++、.NET 小递次等等,无需下载安装递次,一键切换开辟环境。 Cloud Studio供应了完全的 Linux 环境,而且支撑自定义域名指向,动态盘算资本调解,能够完成种种运用的开辟编译与布置。

    原文作者:一歩
    原文地址: https://segmentfault.com/a/1190000016151794
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞