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

Измените модель для представления, лучше ли заменить модель или создать новое представление?

У меня есть вид электронной почты в моем приложении Backbone. В настоящее время он создан в действии view моего контроллера. Это примерно так:

routes: {
  'email/:id': email
},

//...

email: function (id) {
  var email = new Email({
    id: id
  });
  this.emailView = new EmailView({
    model: email
  });
  email.fetch();
}

Теперь проблема в том, что если я нахожусь в одном электронном письме, то другой, я создаю два отдельных EmailView s. Это означает, что, например, ссылка удаления в EmailView привязана к двум отдельным моделям Email, поэтому нажатие кнопки delete удаляет оба (не очень хорошо).

Я рассматриваю два решения. В одном я бы кэшировал EmailView и обновлял свою модель. Проблема в том, что мне пришлось бы повторно связать events в EmailView.

Другим решением было бы создать новый EmailView, как я есть на данный момент, но отвязать старые EmailView.el события перед его заменой.

Я собираюсь сделать это правильно? Есть ли лучший способ справиться с этой ситуацией? Приветствия заранее.

4b9b3361

Ответ 1

Создайте отдельный экземпляр представления для каждого экземпляра модели. Каждый раз, когда вы посещаете новое электронное письмо, выбрасываете старое представление и создаете новое представление с новым экземпляром электронной почты.

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

Вам действительно нужно около 5 классов просмотра.

PageView
    has_one EmailCollectionView on left
    has_one EmailEditorView on right

EmailCollectionView
    has_many EmailSummaryViews as vertical list

EmailEditorView
    has_one EmailView centered

Когда вы щелкаете в элементе EmailCollectionView, вы запускаете событие, которое подхваченный EmailEditorView, который отбрасывает старый экземпляр EmailView и отображает новую версию EmailView

Что-то вроде этого в любом случае

Ответ 2

Мы изначально создавали новые объекты вида каждый раз, когда кто-то перемещался, например. "кандидаты/шоу", как и пример электронной почты. Это представление привязало обработчик к событию 'reset его постоянной модели. Когда мы тогда reset, что модель из командной строки, мы увидим, как много событий стрелять, как были случаи этого представления. Другими словами, это представление не собиралось собирать мусор, даже если элементы, добавленные в DOM, были полностью уничтожены.

Наше решение состояло в том, чтобы просто создать экземпляр наших представлений верхнего уровня один раз, а затем заставить их создавать свои представления в своих методах инициализации. Затем просто переделайте их по мере необходимости. Тогда вам не нужно беспокоиться о сложности сбора мусора (что, насколько я могу судить по нашим экспериментам, не происходит).

Ответ 3

Я думаю, что обработчики событий DOM должны быть удалены вызовом метода remove() view - см. http://api.jquery.com/remove (который называется Backbone звонки под обложками)

Если вы переопределите метод remove(), чтобы удалить привязку к любым событиям модели, как предполагал JohnnyO, сбор мусора должен позаботиться об удалении представления.

В итоге я сделал переопределение метода remove(), чтобы обработать это:

class EmailView extends Backbone.View
    initialize: () ->
        @model.bind('change', @render)
    render: () =>
        # do some stuff
    remove: () ->
        @model.unbind('change', @render)
        super()

Затем вы можете использовать как таковой в маршрутизаторе:

    routes:
      'email/:id': email

    //...

    email: (id) ->
      var email = new Email({
        id: id
      });
      this.emailView.remove() if this.emailView 
      this.emailView = new EmailView({
        model: email
      });
      email.fetch();
    }

Это будет работать, если предположить, что все события в представлении привязаны к правильному элементу - то есть вы используете @el (или this.el) в представлении и что каждый вид имеет свой собственный @el/this.el.