Vivek Pratap Singh
Vivek Pratap Singh

Reputation: 9974

What are passive event listeners?

While working around to boost performance for progressive web apps, I came across a new feature Passive Event Listeners and I find it hard to understand the concept.

What are Passive Event Listeners and what is the need to have it in our projects?

Upvotes: 351

Views: 218553

Answers (4)

Hamid Shoja
Hamid Shoja

Reputation: 4778

if passive:true > preventDefault will have no effect and browser start the default action immediately

  • modern browsers have changed the default value of the passive option to true to not block rendering on document-level nodes Window, Document, and Document.body.

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners

Upvotes: 0

NastyC0ding
NastyC0ding

Reputation: 1

Add this to your JS file to fix the error and add events only to those that need them (scroll, wheel, touchstart, touchmove). All other events will retain their standard behavior.

!function(e) {
    "function" == typeof define && define.amd ? define(e) : e()
}(function() {
    var e, 
        t = ["scroll", "wheel", "touchstart", "touchmove"];

    function supportsPassive() {
        var e = !1;
        try {
            var t = Object.defineProperty({}, "passive", {
                get: function() {
                    e = !0
                }
            });
            window.addEventListener("test", null, t);
            window.removeEventListener("test", null, t)
        } catch (e) {}
        return e
    }

    if (supportsPassive()) {
        var n = EventTarget.prototype.addEventListener;
        e = n;
        EventTarget.prototype.addEventListener = function(n, o, r) {
            var i, 
                s = "object" == typeof r && null !== r,
                u = s ? r.capture : r;
            (r = s ? function(e) {
                var t = Object.getOwnPropertyDescriptor(e, "passive");
                return t && !0 !== t.writable && void 0 === t.set ? Object.assign({}, e) : e
            }(r) : {}).passive = void 0 !== (i = r.passive) ? i : -1 !== t.indexOf(n) && !0;
            r.capture = void 0 !== u && u;
            e.call(this, n, o, r)
        };
        EventTarget.prototype.addEventListener._original = e
    }
});

Upvotes: 0

Carson
Carson

Reputation: 7998

tl;dr If you don't need to use e.preventDefault() in the event, then add passive: true.


This is my understanding of it.

Every event has its default event handling.

We can use addEventListener to add event listeners for a specific event. Within this added event, we can use preventDefault() to avoid executing its default event.

Even if you use preventDefault(), it actually still executes the default event; it just checks whether you have used preventDefault() in its pre-actions. If so, it won't execute. However, checking preventDefault() in the default event incurs significant overhead.

Therefore, if you can inform passive: true within addEventListener, it will significantly speed up the process of determining whether to execute the default event. It will be directly treated as false, meaning it will execute the default event.

<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js"></script>
<div class="mermaid">
flowchart TD
    A[xxxEvent] --> B[default xxxEvent]
    B-->C{check}
    C --> |passive:false| E{preventDefault}
    E --> |true|return
    E --> |false|G[do default event]

    C --> |passive:true| G[do default event]
</div>

enter image description here

Therefore, setting passive: true is a better choice when you don't need to use preventDefault.

Its default value is not true to ensure compatibility.

If it were set to true, older programs using preventDefault would essentially be equivalent to not setting it at all.

Upvotes: 9

Vivek Pratap Singh
Vivek Pratap Singh

Reputation: 9974

Passive event listeners are an emerging web standard, new feature shipped in Chrome 51 that provide a major potential boost to scroll performance. Chrome Release Notes.

It enables developers to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.

Problem: All modern browsers have a threaded scrolling feature to permit scrolling to run smoothly even when expensive JavaScript is running, but this optimization is partially defeated by the need to wait for the results of any touchstart and touchmove handlers, which may prevent the scroll entirely by calling preventDefault() on the event.

Solution: {passive: true}

By marking a touch or wheel listener as passive, the developer is promising the handler won't call preventDefault to disable scrolling. This frees the browser up to respond to scrolling immediately without waiting for JavaScript, thus ensuring a reliably smooth scrolling experience for the user.

document.addEventListener("touchstart", function(e) {
    console.log(e.defaultPrevented);  // will be false
    e.preventDefault();   // does nothing since the listener is passive
    console.log(e.defaultPrevented);  // still false
}, Modernizr.passiveeventlisteners ? {passive: true} : false);

DOM Spec , Demo Video , Explainer Doc

Upvotes: 414

Related Questions