[移动端新特性] Passive Event Listeners

作者:滴滴公共前端团队 - 小春

Passive Event Listeners 这个东西其实有一段时间了,关注 2016 Google I/OMobile Talk 的同学应该有些印象。

PS:

建议一些新技术方向探索的同学关注一下每一年的 Google I/O,而一般大会之后,像类似 medium 网站的一些大咖会有英文的分解。

基本我们很多技术革新或者应用产品化都会从这里面得到一些思考和启发:比如 Polymer 等。

一般新东西我都会问几个问题?

1、它有什么用?

A new feature in the DOM spec that enable developers to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.

Developers can annotate touch and wheel listeners with {passive: true} to indicate that they will never invoke preventDefault.

提高页面的滑动流畅度

PS:

FB 有一个报告:
页面滑动的响应刷新率从 60 FPS 到 30 FPS,会让用户的参与度极速下降

很多人可能对这个数据表现不是很了解,有没有比较主观的数据统计呢?

rbyers.github.io/scroll-late…

如下截图所示:

我们再回顾一下上面的那段话:

1、设置新属性 passive

2、比如在监听 mousewheel 或者 touch 事件中,增加了 passive 为 true 的设置,它就不会调用 preventDefault 来阻止默认滑动行为

3、或者叫:被动监听器

代码片段如下:

function handler () {
    console.log('DDFE');
}
document.addEventListener('mousewheel', handler, {passive: true})复制代码

大家发现:

其实变化就是:前端 DOM 中常用常考的 addEventListener 的第三个参数:之前都是 true | false

2、兼容性?

Chrome 51 开始
Firefox 49

也已经有人做了补丁包:

github.com/WICG/EventL…

github.com/zzarcon/def…

大概的设计流程:
1.判断是否支持:
var supportsPassive = false;
document.createElement("div").addEventListener("test", function() {}, {
    get passive() {
        supportsPassive = true;
        return false;
    }
}
`复制代码
2.覆盖内置的 3 个原型链方法:
// 赋值默认事件原型链的 addEventListener
var super_add_event_listener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener, options) {
    var super_this = this;
    //...
    var wrapped = {
        handleEvent: function (e) {
            e.__passive = passive;
        }
    };
    //...
    super_add_event_listener.call(super_this, type, wrapped, useCapture);

    //...
    super_add_event_listener.call(super_this, type, listener, useCapture);
}复制代码
// 赋值默认事件原型链的 removeEventListener
var super_remove_event_listener = EventTarget.prototype.removeEventListener;
EventTarget.prototype.removeEventListener = function(type, listener, options) {
    var super_this = this;
    //...
    super_remove_event_listener.call(super_this, type, listener, useCapture);
}复制代码
// 赋值默认事件原型链的 preventDefault
var super_prevent_default = Event.prototype.preventDefault;
Event.prototype.preventDefault = function() {
    // 判断是否设置了
    if (this.__passive) {
 console.warn("Ignored attempt to preventDefault an event from a passive listener");
 return;
    }
    super_prevent_default.apply(this);
}复制代码

参考文献:

developers.google.com/web/updates…

medium.com/@devlucky/a… (自备梯子)

github.com/WICG/EventL…

dom.spec.whatwg.org/#dom-eventl…

blog.chromium.org/2016/05/new…

stackoverflow.com/questions/3…

blog.csdn.net/tengxy_clou…

PS:本文插图来自 sofish 大大,感谢


欢迎关注DDFE
GITHUB:github.com/DDFE
微信公众号:微信搜索公众号“DDFE”或扫描下面的二维码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值