我正在参加「掘金·启航计划」
还得从一个页面警告说起,页面里监听了 touchmove 事件,在回调中做了很多事情,导致滑动时出现卡顿,控制台给出了如下的提示
通过提示不难发现,控制台告诉我们在
touchmove 事件花费了太多时间,并指引我们设置 passive。addEventListener() 我们已经很熟悉了,用来在页面中监听事件,但是 passive 是什么?通过 MDN 我们看一下
语法
addEventListener(type, listener, options);
options
-
capture:一个布尔值,是否由捕获阶段开始传播 -
once:一个布尔值,表示只监听一次 -
signalAbortSignal 的 abort() 方法被调用时,监听器会被移除 -
passive:一个布尔值,设置为true时,表示listener永远不会调用preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
重点了解下 passive
在触发一个事件的时候,浏览器并不知道用户是否会调用 preventDefault(),它需要等到事件处理函数执行完后,才能去执行默认行为,这样就会造成一定的卡顿。
在大部分页面中,我们是不会主动调用 preventDefault(),这个方法的,但是浏览器仍然会等待, 利用这一点,我们可以将 passive 设置为 true 以优化滚动的流畅度。
通过一个 gif 来对比下
可以看到,设置 passive 的(左边),明显更流畅,未设置的(右边)滚动时会有明显的卡顿,并且控制台提示了警告。
兼容
一些旧的浏览器,仍然假定第三个参数是布尔值,所以我们需要编写一些代码来兼容,如下。
let passiveSupported = false;
try {
const options = {
get passive() { // 该函数会在浏览器尝试访问 passive 值时被调用。
passiveSupported = true;
return false;
}
};
window.addEventListener("test", null, options);
window.removeEventListener("test", null, options);
} catch (err) {
passiveSupported = false;
}