目录
addEventListener监听器语法:
addEventListener(type, listener, {
capture: false,
passive: false,
once: false
})
type
表示监听事件类型的字符串,如点击事件,聚焦事件。
listener
当所监听的事件类型触发时,监听器会执行一个回调函数,我们可以自定义函数内容。
options 可选
一个指定有关 listener
属性的可选参数对象,三个属性都是布尔类型,并且都默认false。可用的选项如下:
capture
:Boolean
,其值为false时表示冒泡类型,其值为true时表示捕获类型(可以了解一下冒泡和捕获)。once
:Boolean
是否只调用一次,如果其值为true时,表示该监听器是一次性的,执行一次后就被自动 removeEventListener 掉。passive
:Boolean 如果
如果其值为true时,表示listener
永远不会调用preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
例子:对一个按钮绑定“点击事件”的监听器
document.getElementById("testButton").addEventListener("click", function () { ... }, {capture:true , once:true , passive:true});
理解passive
pasive是监听器的第三个参数(此参数是个对象)中的一个属性,其值为布尔值,默认false。
此先,我们需要了解一下这两个事件处理函数:stopPropagation()和preventDefault()
。
e.stopPropagation() 阻止事件冒泡
如果capture是默认值false,即允许事件冒泡。但是我们手动在函数里添加e.stopPropagation() 之后会怎么样呢?它会阻止事件冒泡到父元素,阻止任何父事件处理程序被执行。
e.preventDefault()阻止事件的默认行为
该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)。例如,点击超链接a标签,会默认跳转到href指定的链接。但是如果调用此函数,则不会跳转。
现在在来看看passive,如果当我们把passive的值设置成true时,意味着监听器永远不会调用 preventDefault(),即不会阻止事件的默认行为。如果监听器仍然调用了这个函数(即我们在函数里里写了一句:
e.preventDefault() ),客户端会忽略它,依然不会调用此事件。并且还会抛出一个控制台警告。
很可能还是无法理解passive的作用,以及为何会提升web移动端性能?那我们继续往下分析
passive移动端性能优化
在移动网页中,我们经常使用的就是 touch 系列的事件:比如 touchstart , touchmove , touchend , touchcancel。
以touchstart事件为例,由于 touchstart 事件的默认行为说是滚动当前页面或是缩放页面,如果它的默认行为被阻止了,页面就必须静止不动。但浏览器无法预先知道一个监听器会不会调用 preventDefault(),它能做的只有等监听器执行完后再去执行默认行为,而监听器执行是要耗时的,有些甚至耗时很明显,这样就会导致页面卡顿。即便监听器执行的是个空函数,也会产生一定的卡顿,毕竟空函数的执行也会耗时。而且大多浏览器都不会调用 preventDefault(),所以浏览器白等了那么久。
可能这么说还是很难理解,你可以这样理解:当你触摸滑动页面时,页面应该跟随手指一起滚动。而此时你绑定了一个 touchstart 事件,监听器执行你的事件大概执行 200 毫秒。就这样执行你的函数,之后就要看你的函数中有没有写e.preventDefault()
,如果你在事件绑定函数中调用了 preventDefault,那么页面就不应该滚动,如果你没有调用 preventDefault,页面就需要滚动。但是你到底调用了还是没有调用,浏览器不知道。只能先开始执行你的函数,等 200 毫秒后,绑定事件执行完了,浏览器才知道,“哦,原来你没有阻止默认行为,好的,我马上滚”。此时,页面开始滚。这样页面就会出现一定的延迟,效率低下
但是passive的出现就解决了这一问题,把passive 的值设置成true,一上来就告诉浏览器:“我不调用 preventDefault 函数来阻止事件事件行为”,这样当浏览器就不会等待你下达命令,那么浏览器就能快速生成事件,页面就会立马随着你的手指滚动起来,从而提升页面性能。