Отмена привязки событий при прокрутке — рекомендуется?

мой сайт построен на магистрали. Он имеет пользовательский интерфейс на основе ленты, что означает, что в ленте часто отображается большое количество контента. Примерно к каждому элементу привязано около 30 событий.

Притормаживает после прокрутки пары страниц вниз.

Имеет ли смысл отвязывать элементы, которые были прокручены, и снова связывать их, когда они прокручиваются?

  • Если это так, некоторая помощь (пример кода / указатели на ресурсы были бы отличными)
  • Может ли быть что-то, что вызывает медлительность?

person ming yeow    schedule 07.01.2013    source источник


Ответы (1)


Трудно сказать, вызвана ли медлительность обработчиками событий или просто тем, что браузер не может обработать огромное количество узлов DOM на странице, или по какой-либо другой причине.

Вот быстрое решение для отмены делегирования событий для представлений, которые не находятся в текущем окне просмотра. Это не совсем готово к производству, но должно помочь вам проверить, являются ли обработчики событий причиной проблемы с производительностью.

(здесь работает JSFiddle, также проверьте консоль браузера)

var View = Backbone.View.extend({

  onScroll: function() {

    var wasInView = this.isInView;
    var isInView = this.checkIsInView();

    if(wasInView === true) {
      if(!isInView) {
         this.undelegateEvents(); 
      }
    } 
    else if(wasInView === false) {
      if(isInView) {
        this.delegateEvents();
      }
    }
    else {
      //first pass
      if(!isInView) {
        this.undelegateEvents();
      }
    }

    this.isInView = isInView;
  },

  checkIsInView: function() {
    var $el = this.$el,
        top = $el.offset().top,
        bottom = top + $el.height(),
        windowTop = $(window).scrollTop(),
        windowBottom = windowTop + $(window).height();

    return ((bottom <= windowBottom) && (top >= windowTop));
  },

  render: function () {

    //rendering code here...

    if(!this.lazyScroll) {
      //wait for scroll events to stop before triggering scroll handler
      this.lazyScroll = _.debounce(_.bind(this.onScroll, this), 50);
      $(window).bind('scroll', this.lazyScroll)
               .bind('resize', this.lazyScroll); 
    }

    return this;
  },

  remove: function() {
    if(this.lazyScroll) {
      $(window).unbind('scroll', this.lazyScroll)
               .unbind('resize', this.lazyScroll); 
      delete this.lazyScroll;
    }
    Backbone.View.prototype.remove.apply(this, arguments);
  }
});
person jevakallio    schedule 07.01.2013
comment
спасибо @fencliff! Я проверю это и вернусь к вам. спасибо еще раз миллион :) - person ming yeow; 09.01.2013
comment
я реализовал версию этого после тестирования! оказывается, что это не очень помогло производительности в начале, но предотвратило чрезмерные проблемы с памятью при прокрутке. - person ming yeow; 18.01.2013