JS 中的事件和事件代理

391 阅读2分钟

这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

hi 我是小十七_,今天是大年初九,之前整理了一些关于JS事件的比较基础的知识,在这里分享给大家。

事件的三个阶段

1.捕获:从 window对象 到 目标节点 2.目标:在 目标节点 上触发 3.冒泡:从 目标节点 到 window对象

codepen.io/ubuntugx/pe…

为DOM元素注册事件处理函数

EventTarget.addEventListener

myButton.addEventListener('click', function(){}, false);

注意: Internet Explorer 6-8 并不支持这个方法,而是提供了类似的 element.attachEvent API 。如果要进行跨浏览器使用,请考虑使用有效的JavaScript 库。 codepen.io/ubuntugx/pe… 两者不同:

  1. ie8 及以下不支持捕获,因此 attachEvent 没有第三个参数
  2. attachEvent 的第一个参数前面有 'on'
  3. 函数中的 this 指向不同 attachEvent 中 this 指向 window,addEventListener 指向当前正在处理的对象

优点:

  1. 一个事件可以注册多个监听器
  2. 可以选择捕获或者冒泡(其他两种只能在冒泡阶段触发)
  3. 对任意的 DOM 元素有效,不光是 HTML 元素

HTML 属性

<div onclick="alert('clicked!')"></div>

缺点:会使 html 中标记的数量变大,可读性差,没有做到行为和结构分离,bug 不好追溯

DOM 元素属性

myButton.onclick = function(){console.log('clicked!')}

缺点:每个元素和事件只能设置一个处理函数

codepen.io/ubuntugx/pe…

事件代理也叫事件委托

利用事件传播过程中的事件冒泡,在父元素上监听事件,根据 e.target 判断触发事件的元素。

<ul>
	<li></li>
	<li></li>
</ul>
document.querySelector('ul').addEventListener('click', function(e){
	if(e.target.tagName.toLowerCase === 'li'){
		console.log('clicked!')
	}
}, false)

优点:

  1. 不需要循环进行事件注册、函数声明,减少内存开销
  2. 动态渲染元素时,新元素增加不用再次绑定事件

codepen.io/ubuntugx/pe…

e.target 和 e.currentTarget

e.target

触发事件的元素

e.currentTarget

当前注册事件的元素(比如调用 addEventListener 的 DOM 对象)

codepen.io/ubuntugx/pe…

this 指向

使用 addEventListener 为元素注册事件,this 为该元素的引用。 使用 html 的事件属性时,后面传的字符串在执行时会被包裹到一个函数中,函数的 this 指向和 addEventListener 一致。 所以:

<table id="t" onclick="modifyText();">

function(){
	// this 指向 table DOM 对象
	modifyText();  // this 指向 window(严格模式 undefined)
}

期望修改 this 指向,可以使用 bind,但是要注意保存函数的引用,以便解绑时使用。

developer.mozilla.org/zh-CN/docs/…

codepen.io/ubuntugx/pe…