2016-02-03 3 views
4

Я подозреваю, что способ обработки представлений в backbone.js является ошибочным, так как он создает «утечку памяти» ».Неоднократно создавая и уничтожая виды в Backbone.js или Marionette.js, не создавая «утечку памяти»

Существует вид, который постоянно переписывается другой копией самого себя. Новая копия связана с другой моделью.

Я создаю и добавляю представление к его родительскому виду, установив параметр el при создании дочернего представления.

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

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

var parent = new (Backbone.Marionette.ItemView.extend({ 
    ui:{ 
      child_container: '#child-container' 
    }, 
    onRender: function(){ 
      // Listen to outside event 
      ... 
    } 
    on_Outside_Event: function(new_model){ 
      // Quick fix prevents multiple alerts popping up for every child view when "button" is pressed 
      this.child_view.destroy_view(); 

      // New child view is created and rendered on top of the one that was there before 
      this.child_view = childView({ 
       el: this.ui.child_container, // <-- Is this the problem? 
       model: new_model 
      }) 
      this.child_view.render(); 
    } 
}))(); 

var childView = Backbone.Marionette.ItemView.extend({ 
    events:{ 
      'click button': 'on_click_button' 
    }, 
    on_click_button: function(){ 

      // Alert pops up once for every view that was ever displayed. 
      alert('Button clicked'); 
    }, 
    // QUICK FIX 
    destroy_view: function(){ 
      this.undelegateEvents(); 
    } 

}) 

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

При нажатии на кнопку «Отменить назначение», эта функция вызывается для каждого назначения, который каждый отображается в этой области, хотя я слушаю случае не используя: events:{ 'click #cancel-button': 'on_button_click'}

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

enter image description here

Возможное исправление ?

Немного искал, делает ли это исправление адекватным?

Обычно, я думаю, что функции removeData().unbind(); и remove() называются непосредственно на this.$el, но это не работает здесь, я думаю, потому что я добавил мнение ребенка с помощью опции el, когда она была создана (el: this.ui.child_container)

var childView = Backbone.Marionette.ItemView.extend({ 
    ... 
    // REAL FIX 
    destroy_view: function(){ 
      this.undelegateEvents(); 

      this.$el.children().removeData().unbind(); 
      this.$el.children().remove(); 
    } 

ответ

2

Я думаю, что вы должны сделать ваш родитель просмотр LayoutView (это просто ItemView с дополнительными функциями для обработки областей IIRC), имеет область, определенную для которого вы хотите этот взгляд ребенка появляется, а затем сделать:

Parent = Backbone.Marionette.LayoutView.extend 
    regions: 
     child: "#child-container" 

    on_Outside_Event: -> 
     childView = new ChildView(...) 
     @getRegion("child").show(childView) 

(извините, что я использовал coffeescript, быстрее писать, но вы можете легко перевести).

марионетки будут обрабатывать все: закрыть свой старый вид ребенка, Несвязанность событие и т.д.

+0

Когда я впервые начал использовать марионетка, я Раскладка несколько раз, но я не думаю, что я очень хорошо понимал их.Это приложение большое, существует множество уровней родительских представлений и представлений для детей. Есть ли времена, когда нормально встраивать макеты? Если я правильно понимаю, обычно не рекомендуется повторно отображать макет (я почти никогда не пересматриваю виды в любом случае)? Когда вы будете использовать ItemView, а не макет? Благодаря! –

+0

Макеты очень полезны, и тот факт, что они являются гнездовыми, является одной из вещей, которые делают их отличными. В документе о марионетке упоминается, что они гнездятся по своему усмотрению. Но вы правы, вам следует избегать повторного рендеринга большого «дерева» вложенных макетов. Но есть много способов избежать этого, как правило, просто привязывая взгляды вашего ребенка к их модели или к тому, что меняется, и заставляя их повторно отображать самих себя. Например, в вашем примере, почему бы вам просто не обновить модель дочернего представления с данными новой модели, заставив ее повторно отобразить? Вместо того, чтобы заменить его новым? – Robin

+0

Я не обновляю модель детского вида с новой информацией, потому что есть только одна копия каждой модели. Одна модель иногда стоит за несколькими видами. В этом примере вид детализации встречи на левой стороне и вид назначения в календаре с правой стороны используют ту же модель. Так, например, при изменении «start_time» назначения в подробном представлении позиция назначения в календаре будет фактически изменяться по мере того, как пользователь будет вводить данные. В будущем я хотел бы добавить push-обновления моделей с сервера. Когда это произойдет, все представления будут обновляться. –