Подтвердить что ты не робот

Когда использовать bindTo, привязать или включить с помощью Backbone.Marionette?

На этот раз я борюсь с различными методами привязки событий. У меня есть все упомянутые методы в моем коде. Я просто не знаю, если я на правильном пути. Может быть, я всегда должен использовать bindTo, чтобы убедиться, что мои взгляды полностью закрыты после изменения (в настоящее время это часто приводит к ошибкам)? Есть ли какие-либо передовые методы, которые помогут мне в правильном направлении?

Чтобы проиллюстрировать мое нынешнее понимание Marionette, здесь один модуль из моего приложения. Как всегда, каждый намек приветствуется.

PP.module('Grid', function(Grid, PP, Backbone, Marionette, $, _){

  Grid.Product = Backbone.Model.extend({});

  Grid.ProductCollection = Backbone.Collection.extend({
    model: Grid.Product,
    url: '/products/query'
  });

  Grid.ProductView = Backbone.Marionette.ItemView.extend({
    className: 'grid',
    template: 'public/templates/grid-template'
  });

  // Helper Methods
  // -----------------------

  var getGenderCode = function(genderName){
    var genderMap = {
      'men': 'M',
      'women': 'W',
      'unisex': 'A'
    }

    return genderMap.genderName;
  }

  // Public API
  // -------------------

  Grid.renderGrid = function(productCollection){
    Grid.productView = new Grid.ProductView({
      collection: productCollection
    });

    Grid.productView.bind('show', function(){
      $('#isotope-container').isotope({
        itemSelector : '.item',
        containerStyle: {
          position: 'relative',
          zIndex: 1
        }
      });
    });

    PP.Layout.mainRegion.show(Grid.productView);
  }

  // Event Handlers
  // -----------------------

  PP.vent.bind('grid:requested', function(categoryData){
    // use bootstrapped data on first start
    if (PP.App.bootstrappedCategoryName !== categoryData.categoryName) {
      Grid.productCollection.fetch({
        data: {
          gender: getGenderCode(categoryData.categoryName),
          category: categoryData.categoryId
        }
      });
    }
    else {
      PP.vent.trigger('mainview:ready', {
        categoryName: PP.App.bootstrappedCategoryName
      });
    }
  });

  // Initializer
  // --------------------

  PP.addInitializer(function(options){
    Grid.productCollection = new Grid.ProductCollection();

    Grid.productCollection.on('reset', function(){
      Grid.renderGrid(Grid.productCollection);
    });

    Grid.productCollection.reset(options.newArrivalsList);
  });
});
4b9b3361

Ответ 1

общие рекомендации заключаются в том, что каждый раз, когда у вас есть объект, который создается и уничтожается на протяжении всего срока службы приложения, и этот объект должен связываться с событиями из какого-либо другого объекта, вы должны использовать EventBinder.

Виды и утечки памяти

Представления - прекрасный пример этого. Виды создаются и уничтожаются все время. Они также привязываются к множеству разных событий из model и collection в представлении. Когда представление уничтожается, эти события необходимо очистить. Используя встроенный метод bindTo в представлении, обработчики событий будут очищены для вас. Если вы не используете bindTo и вместо этого используете on напрямую, вам придется вручную вызвать off, чтобы развязать события, когда представление закрыто/уничтожено. Если вы этого не сделаете, у вас появятся зомби (утечки памяти).

Если вы еще не прочитали их, ознакомьтесь с этими статьями:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

http://lostechies.com/derickbailey/2012/03/19/backbone-js-and-javascript-garbage-collection/

Пользовательские группировки событий

Представления - это не единственное место, где это применимо, но не единственный вариант использования для EventBinder.

Если вы работаете с несколькими объектами, привязаны к их событиям, и эти объекты могут быть заменены другими экземплярами объектов, тогда полезно использовать EventBinder. В этом случае подумайте о EventBinder как о коллекции или группе событий для связанных объектов.

Скажем, у вас есть ObjA, ObjB и ObjC. Каждый из них вызывает некоторые события, и вы хотите, чтобы вы очистили обработчики событий, когда ваш код будет выполнен. Это легко сделать с помощью EventBinder:



doStuff = {

  start: function(a, b, c){
    this.events = new Marionette.EventBinder();
    this.events.bindTo(a, "foo", this.doSomething, this);
    this.events.bindTo(b, "bar", this.anotherThing, this);
    this.events.bindTo(c, "baz", this.whatever, this);
  },

  doSomething: function(){ /* ... */ },
  anotherThing: function(){ /* ... */ },
  whatever: function(){ /* ... */ },

  stop: function(){
    this.events.unbindAll();
  }

}

doStuff.start(ObjA, ObjB, ObjC);

// ... some time later in the code, stop it

doStuff.stop();

Вызов stop в этом коде будет правильно очищать все обработчики событий для этого использования.

Когда использовать on/off Непосредственно

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

В ситуациях, когда обработчики событий не нуждаются в очистке, нет необходимости использовать EventBinder. Это может быть событие, которое запускает роутер или запускает объект Marionette.Application. Для этих событий жизненного цикла приложения или событий, которые необходимо прожить на протяжении всей жизни приложения, не беспокойтесь с помощью EventBinder. Вместо этого просто включите обработчики событий. Когда человек обновит окно браузера или перейдет на другой сайт, обработчики будут очищены в этой точке.

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