In 2020 do i need to call "removeEventListener" on 2nd initialization?

83 Views Asked by At

I have continuous animation, made with gsap library. I'm using mouseover/mouseout events to pause/resume this animation. On window resize event I'm making re-initialization. My question is: do I need to call removeEventListener on 2nd initialization?

Here is the code/scenario:

const scroll = {

    create: function (el) {

        this.scrollAnimation = gsap.timeline({
            repeat: -1
        });

        // another piece of awesome code here...

        this.create__addMouseEvents(el);
    },
    create__addMouseEvents: function (el) {

        // here, on window resize event( when i call update(), during re-initialization ), do i need to call "removeEventListener"?

        el.addEventListener('mouseover', () => this.scrollAnimation.pause());

        el.addEventListener('mouseout', () => this.scrollAnimation.resume());

    },

    update: function () {
        // 
        // destroy old "scrollAnimation" if it's already exists
        if (this.scrollAnimation) {
            this.scrollAnimation.kill();
        }
        // 
        // reinit
        this.init();
    },

    init: function () {
        
        // some awesome code here...

        this.create(el);
    }
}


document.addEventListener('DOMContentLoaded', function () {
    
    scroll.init();

});


let windowResizeTimer;
window.addEventListener('resize', function () {
    
    clearTimeout(windowResizeTimer);
    
    windowResizeTimer = setTimeout(function () {
        
        scroll.update();

    }, 150);

});
1

There are 1 best solutions below

0
On BEST ANSWER

you are currently adding a new event to the browser with every update. A simple solution would be the following:

const scroll = {
  eventsAlreadyAdded: false,
  create: function (el) {
    this.scrollAnimation = gsap.timeline({ repeat: -1 });
    // another piece of awesome code here...

    if (!scroll.eventsAlreadyAdded) {
      this.create__addMouseEvents(el);
      scroll.eventsAlreadyAdded = true;
    }
  },
  create__addMouseEvents: function (el) { /* .. */ },
  update: function () { /* .. */ },
  init: function () { /* .. */ }
}

Since you are not instantiating the scroll object, you have to change the global reference scroll.eventsAlreadyAdded.

Alternatively, you can slightly rewrite the code so that you are working on a instantiated variable (not tested):


class Scroll {
  /**
   * Returns the element
   * @type {Node}
   */
  static get element() {
    return document.querySelector('THE ELEMET SELECTOR');
  }

  /**
   * Initial the scroll event to given element
   * @param {Node} el the element that will get an animation
   */
  constructor(el) {
    this.el = el;

    /**
     * Remembers whether the events have already been attached to the element
     * @type {boolean}
     */
    this.eventsAlreadyAdded = false;

    /**
     * The timeline instanze from gsap
     * @type {Timeline}
     */
    this.scrollAnimation = null;

    this.create();
  }

  create() {
    this.scrollAnimation = gsap.timeline({
      repeat: -1
    });

    // another piece of awesome code here...
    this.addMouseEvents();
  }

  addMouseEvents() {
    if (this.eventsAlreadyAdded) return;
    this.el.addEventListener('mouseover', () => this.scrollAnimation.pause());
    this.el.addEventListener('mouseout', () => this.scrollAnimation.resume());
    this.eventsAlreadyAdded = true;
  }

  update() {
    if (this.scrollAnimation) {
      this.scrollAnimation.kill();
    }
    this.create();
  }
}

let scroll = null;
let windowResizeTimer = null;

document.addEventListener('DOMContentLoaded', () => {
  scroll = new Scroll(Scroll.element)
});

window.addEventListener('resize', () => {
  if (!scroll) return;
  if (windowResizeTimer) clearTimeout(windowResizeTimer);
  windowResizeTimer = setTimeout(() => { scroll.update(); }, 150);
});