手機瀏覽器在滾動當前頁面(還多是縮放頁面)時,因爲默認行爲被阻止,致使頁面被迫靜止,致使用戶使用體驗差,感受滾動頁面有停頓感。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 代碼和瀏覽器的默認行爲了。事件