比较jQuery on方法和原生DOM的事件监听器

背景:
今天写代码时使用了一下jQuery的事件监听,于是与原生DOM操作进行了比较,特别是event对象和this的指向两者之间的异同。
复制代码

为什么进行比较

为什么我要抠这个细节?主要是避免使用时不至于混淆this或event.target指向的元素而出现莫名其妙的问题。第二个原因是强迫症(请忽略..).

开始比较

第一次比较

有如下html片段:

目标:委托 #outer 作为监听者,点击a#one元素,观察ev.target及this的指向

<div id="outer">
   <div><a id="one" href="ca.html">ONE</a></div>
    <a id="two" href="cb.html">ONE</a>
    <a id="three" href="cc.html">ONE</a>
</div>
复制代码

事件处理程序:

function test(ev) {
    console.log(ev.target);
    ev.preventDefault();
    console.log(this);
}
复制代码
  • 原生DOM
var el = document.getElementById('outer');
el.addEventListener('click',testfalse); 
复制代码
  • jQuery
$('#outer').on('click',test);
复制代码

结果:

不出所料,this指向监听者div#outer,ev.target指向了a#one,而且原生DOM和jquery的输出结果一样。这与我们的直觉一致。



第二次比较

jQuery加入了一个选择器,筛选了div#outer 下面的a元素,同样点击a#one 元素

$('#outer').on('click',test);
复制代码

结果:



第二次使用,jquery的this却指向了a#one,不再是监听者div#outer,看起来有点奇怪.

你可能会觉得,添加了选择器,是不是相当于给a元素也添加了监听器,如果是这样的话我为什么不写成下面的第二种形式呢?

$('#outer').on('click','a',test);
复制代码

而且输出还和上面一致也是log出来两个a元素,所以得出结论:这两行代码等价!



可是,先感性地想想,和前面的写法的结果一样,所以第一种写法是多余的吗?如果我的#outer里面有很多个a子元素,使用第二种写法,不就添加了很多事件监听器吗?事件委托不就失去了作用?所以我相信jquery的设计者们没那么笨,这么写一定有它的原因.

我再认真观察了以下DOM结构,发现浏览器的处理方法明显不一样:

对于$('#outer').on('click','a',test); 这种写法,只有被委托的父元素创建了事件监听对象.



对于$('#outer a').on('click',test); 这种写法,每一个a元素都绑定了事件,如果a的元素很多,那么可以预见的问题是页面性能下降.


好了,结论出来了,我们可以猜想,第一种写法,与一般的事件委托大同小异,委托了父元素进行监听.但又仅对a元素的点击产生响应.

你可能会问,真的只对a元素产生响应吗?感性的想法那当然是,不然这样设计接口的意义就不存在了.

第三次比较

于是,我们可以考虑一下,jquery的事件监听方法大致等价于:

function test(ev) {
  if (ev.target.tagName === 'A') {
     console.log(ev.target);
     ev.preventDefault();
     console.log(this);
  }
  
var el = document.getElementById('outer');
el.addEventListener('click',test,false); 
复制代码

嗯~看起来有点那么回事,先进行条件判断,如果元素名是a那么才执行代码块,大体上逻辑没问题,可是...

点击一下a#one 试试,结果:



嗯?跟jquery的不一样来着,刚才我们已经发现了,使用jquery的on方法,this指向了产生事件对象的元素,即a#one 而原生DOM的this指向了事件监听者div#outer指向事件监听者更符合我们的认知.

不过我们还是可以得出结论,jquery的on方法的selector参数,类似于在事件委托的基础上做了一次if判断,只有符合结果的元素才会响应事件.

那么,ev.target 还是 this?

ev.target和this哪一个更好呢?

综合以上比较,我认为需要分情况灵活应用,因为:

  1. this有可能指向监听者,这有时候往往是我们想要的,特别是创建了多个事件监听器的时候.
  2. 一旦处理程序被包裹在匿名函数中,this的指向就会发生变化,而ev.target却始终保持一致.这时ev.target是更好的选择.
  3. 值得注意的是,如果使用this,jquery(在on方法传入selector参数的情况下)和原生DOM的this指向还会不一样.jquery的on方法里面的this跟ev.target一样,但原生DOM的this却指向事件监听者.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值