导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

参数

once

监听器函数被调用一次后会被自动移除,下次调用不会触发该函数了

注意:

Untitled

⭐️ passive

如果设置为 true,会导致当前事件处理函数永远不会调用内部设置的 event.preventDefault(),并且会在设置了 event.preventDefault() 的时候报警告。

Untitled

使用 passive 改善的滚屏性能

前置知识

某些浏览器(特别是Chrome和Firefox)已将文档级节点 WindowDocumentDocument.bodytouchstart (en-US)touchmove (en-US) 事件的 passive 选项的默认值更改为 true。这可以防止调用事件监听器,因此在用户滚动时无法阻止页面呈现。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    * {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .container {
      width: 100px;
      height: 1500px;
      background-image: linear-gradient(#e66465, #9198e5);
    }
  </style>
</head>
<body>
  <div class="container">
  </div>
  <script>
    window.addEventListener('touchstart', function(e) {
      e.preventDefault();
      console.log(123);
    }, {

    });
  </script>
</body>
</html>

Untitled

用鼠标上下移动界面时,控制台会报警告:

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

这是因为 chrome 默认给 window、document 和 document.body 的事件监听函数中的 passive 默认设置为 true 了,所以导致上边代码报错。


如果此时我们把 passive 设置为 false,会发现一个特别的现象,我们无法再通过触摸页面让其上下滚动了(鼠标滚轮除外):

<!DOCTYPE html>
<html lang="en">
<head>
  ...
</head>
<body>
  <div class="container">
  </div>
  <script>
    window.addEventListener('touchstart', function(e) {
      e.preventDefault();
      console.log(123);
    }, {
      passive: false
    });
  </script>
</body>
</html>

原因:

在给 window 添加了 touchstart 事件处理函数后,浏览器的处理顺序是:

  1. 先执行这个事件处理函数 console.log(123)
  2. 等待 handler 回调执行完后,再执行浏览器默认行为 scroll

所以由于在事件处理函数中设置了 e.preventDefault ,阻止了浏览器默认行为 scroll。从而导致无法上下滚动了

滚屏性能

那么所谓的滚屏性能在哪儿呢:

  1. handler 处理器程序执行 console.log(123)
    1. 非常大的性能问题在于:等待的时间浪费,从而导致 scroll 的卡顿
  2. 执行默认行为 scroll

所以浏览器把 passive 默认设置为了 true,目的:

  1. 阻止默认行为的方法 event.preventDefault 不会被调用
  2. 使用两个线程去处理滚动性能问题:
    1. 线程1:处理 handler 的程序执行
    2. 线程2:执行默认行为
  3. 从而解决了 handler 程序执行的等待时间问题

event.cancelable

表明该事件是否可被取消

Event 实例的只读属性 cancelable 表明该事件是否可以被取消,当事件被阻止之后,该事件就好像没有被触发一样。如果事件不能被取消,则其 cancelable 属性的值为 false,且事件发生时无法在事件监听回调中停止事件。

在许多事件的监听回调中调用preventDefault()前,都需要检查 cancelable 属性的值。

大部分由用户与页面交互产生的原生浏览器事件都可以被取消。取消click (en-US)scroll (en-US)beforeunload (en-US) 事件将分别阻止用户点击某些元素,滚动页面或跳离页面。

使用其它 JavaScript 代码创建的 Custom events ,可以在初始化事件的时候控制该事件是否可以被取消。