简体   繁体   中英

DOM event handling with ES6 class methods

I'm not entirely certain whether or not StackOverflow is the correct place to bring this topic up, but I guess I'll be corrected if I'm wrong.


I'm asking myself, what is a "better practice" to deal with DOM event handlers within a prototype-chain (or ES6 "class").

Problems arise if you bind a method like:

node.addEventListener('click', this.clickHandler, false);

(full example below)

You obviously lose your this context when that method gets invoked. We can solve this issue by binding the context to that very method ( this.clickHandler.bind( this ) ). The only problem in using this technique is, that bind() will return another function reference of course. That in turn means, you cannot just simply remove that handler by calling

node.removeEventListener('click', this.clickHandler);

because you're dealing with different functions. The only way that I could think of so far would be, to create that bound method before you attach it to the event and also store it in your this context variable:

this._boundClickHandler = this.clickHandler.bind( this );
node.addEventListener('click', this._boundClickHandler, false);

Yes this does the job, but it seems very ugly and not very intuitive. Are there better patterns to solve this kind of issues within an ES6 class ?

class foo {
    constructor() {
        this._boundClickHandler = this.clickHandler.bind( this );
        document.body.addEventListener( 'click', this._boundClickHandler, false );
    }

    clickHandler( event ) {
        // do stuff
        document.body.removeEventListener( 'click', this._boundClickHandler );
    }
}

ES6 itself doesn't have the solution you'd like, but you can use ES7 Class Properties:

class foo {
    constructor() {
        document.body.addEventListener('click', this.clickHandler, false );
    }

    clickHandler = event => {
        // do stuff
        document.body.removeEventListener('click', this.clickHandler);
    }
}

clickHandler, being a fat-arrow function, has 'this' context bound to the class instance, which is exactly what you want

You can also use the defaults options available in ES6 and return events:

 class foo { static defaults() { return { events: { "click .node_identifier": "nodeClick" } }; } nodeClick(e) { //Do stuff } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM