手机浏览器在滚动当前页面(还多是缩放页面)时,因为默认行为被阻止,致使页面被迫静止,致使用户使用体验差,感受滚动页面有停顿感。web
具体一点的解释:因为 touchstart 事件对象的 cancelable 属性为 true,也就是说它的默认行为能够被监听器经过 preventDefault() 方法阻止。但浏览器没法预先知道一个监听器会不会调用 preventDefault(),它能作的只有等监听器执行完后再去执行默认行为,而监听器执行是要耗时的,有些甚至耗时很明显,这样就会致使页面卡顿。即使监听器是个空函数,也会产生必定的卡顿,毕竟空函数的执行也会耗时。浏览器
基本概念:xxx.addEventListener('事件名', function(xxx){xxx}, useCapture).
第一个参数表示事件名称(不含 on,如 "click");第二个参数表示要接收事件处理的函数;第三个参数为 useCapture.app
下面就来看看这个东西是个啥意思,直接举例子说明更加直观。webapp
<div id="level1"> <div id="level2"> <div id="level3">请在此点击</div> </div> </div> <div id="info"> </div>
var level1 = document.getElementById("level1"); var level2 = document.getElementById("level2"); var level3= document.getElementById("level3"); var info = document.getElementById("info"); outDiv.addEventListener("click", function () { info.innerHTML += "level1" + "<br>"; }, false); middleDiv.addEventListener("click", function () { info.innerHTML += "level2" + "<br>"; }, false); inDiv.addEventListener("click", function () { info.innerHTML += "level3" + "<br>"; }, false);
根据上述代码来看这个 useCapture 为 true 和 false的做用效果:函数
全为 false 时,触发顺序为:level三、level二、level1 全为 true 时,触发顺序为:level一、level二、level3 level1为 true,其余为 false 时,触发顺序为:level一、level三、level2 level2为 true,其余为 false 时,触发顺序为:level二、level三、level1 level3为 true,其余为 false 时,触发顺序为:level三、level二、level1 level1为 false,其余为 true时,触发顺序为:level二、level三、level1 level2为 false,其余为 true时,触发顺序为:level一、level三、level2 level3为 false,其余为 true时,触发顺序为:level一、level二、level3
由上述结果得出以下结论:线程
true 的触发顺序老是在 false 以前; 若是多个均为 true,则外层的触发先于内层; 若是多个均为 false,则内层的触发先于外层。
使用方式以下code
addEventListener('事件名', function(xxx){xxx}, { capture: false, passive: false, once: false })
三个属性都是布尔类型的开关,默认值都为 false。对象
capture:等价于之前的 useCapture 参数; once:就是代表该监听器是一次性的,执行一次后就被自动 removeEventListener 掉; passive:用于webapp的touch事件
据了解,在手机浏览器使用事件的时候,有 80% 的滚动事件监听器是不会阻止默认行为的,也就是说大部分状况下,浏览器是白等了。因此,passive 监听器诞生了,passive 的意思是“顺从的”,表示它不会对事件的默认行为说 no,浏览器知道了一个监听器是 passive 的,它就能够在两个线程里同时执行监听器中的 JavaScript 代码和浏览器的默认行为了。事件