sachinchoolur / lightGallery

A customizable, modular, responsive, lightbox gallery plugin.
https://www.lightgalleryjs.com/
Other
6.55k stars 1.29k forks source link

Performance issue in lgQuery.prototype.off() #1666

Open pweerd opened 1 month ago

pweerd commented 1 month ago

Description

I have a gallery with 1000 items. I noticed that the web page is getting less and less responsive (it takes seconds!) after a few page views. (on every page view I need to do a .refresh() of the gallery, since the list of photo's will be changed.

I tracked this down to a problem in lgQuery.prototype.off(). Current code is

            Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
                if (_this.isEventMatched(event, eventName)) {
                    lgQuery.eventListeners[eventName].forEach(function (listener) {
                        _this.selector.removeEventListener(eventName.split('.')[0], listener);
                    });
                    lgQuery.eventListeners[eventName] = [];   //<-----
                }
            });

I think this should be:

            Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
                if (_this.isEventMatched(event, eventName)) {
                    lgQuery.eventListeners[eventName].forEach(function (listener) {
                        _this.selector.removeEventListener(eventName.split('.')[0], listener);
                    });
                    delete lgQuery.eventListeners[eventName];   //<-----
                }
            });

Also I was wondering if this should be a double keyed object. First key is the namespace, 2nd key is the eventname. Like lgQuery.eventListeners[ns_part][name_part]. This prevents the double loop and in case of 1000 gallery items, it saves a million calls to isEventMatched()!

Steps to reproduce

Simply put 1000 items in the gallery and call lg.refresh() a few times.

JS code that you use to initialize lightGallery.

      _lg = lightGallery($elt[0], {
         mode: 'lg-fade',
         captions: false,
         lastRow: "hide",
         rowHeight: 500,
         margins: 50,
         preload: 1,
         download: true,
         selector: selector,
         slideShowInterval: 2500,
         closeOnTap: false,
         plugins: [lgVideo, lgAutoplay, lgFullscreen],   //, lgThumbnail lgZoom,, lgHash
         mobileSettings: {
            showCloseIcon: true,
            closable: true,
            controls: false,
            download: false
         }
      });

Sample HTML markup

Environment

Additional context