Прехвърлянето на Backbone модел от колекция към нов изглед запазва колекцията в паметта

Имам CompositeView, който показва списък с модели, които поисках от сървър, нещо като (в CoffeeScript):

class List.Stories extends Marionette.CompositeView
    template: "stories-list-body"
    itemView: List.Story
    itemViewContainer: "#stories-list"

class List.Story extends Marionette.ItemView
    template: "stories-list-story"
    triggers:
        "click .js-show-button": "show:button:clicked"

Изгледите са създадени правилно, предавайки колекцията като аргумент за конструктора, мога да видя елементите и когато щракна върху бутона, той задейства съответното събитие и то се обработва. Работата е там, че когато манипулаторът създаде нов изглед, показващ модела, и затвори стария, колекцията все още се препраща в model.collection, като заема малко памет.

Какъв би бил правилният начин за премахване на тази препратка? Просто използване на delete model.collection в манипулатора преди замяна на изгледа?


person JayC    schedule 05.03.2014    source източник


Отговори (2)


Опитайте да направите нещо подобно

var model = myCollection.remove(viewModel, { silent: true })

// create new view using `model`

В примера по-горе viewModel ще се отнася до модела на изгледа (така че ще бъде this.model от изгледа).

Като премахнете модела от колекцията, той трябва да бъде събран за боклук (ако приемем, че не е споменат никъде другаде...).

person David Sulc    schedule 05.03.2014
comment
Добавих кода в модифицирана версия на метода view.close, преди да извикам оригиналното затваряне. Той премахва всички модели от колекцията, оставяйки колекция без елементи, но колекцията все още е там. Не се споменава от модела както преди, така че ще трябва да търся къде се споменава (DevTools е малко загадъчен) - person JayC; 06.03.2014
comment
Проверете on слушателите на събития, за да видите дали случайно няма препратка към колекцията в някой от тях... - person David Sulc; 06.03.2014
comment
Не използвам никакви on, само listenTo, за да гарантирам, че Marionette/Backbone ще почисти вместо мен. - person JayC; 06.03.2014
comment
Мисля, че открих теча. Премахването на моделите, както предложихте, оставя само препратки от системата (GC, bound_this и т.н.) и оригиналния съставен изглед, който се препраща само от системата, така че предполагам, че Chrome не обработва добре тези препратки. - person JayC; 06.03.2014

Ако всичко се случи в рамките на един и същ контролер, т.е. контролерът все още е отворен и ще бъде отговорен за събитието и няма да се задейства Application.vent, мисля, че тази ситуация е приемлива, ако изтичането на памет няма да бъде голямо. Причината е, че контролерът ще бъде окончателно затворен, така че няма нужда да бързате.

Ако вентилация/заявка/команда на ниво приложение ще бъде задействана, трябва да го приемете сериозно. Да предположим, че имате такъв код в контролера:

@listenTo storiesView, 'itemview:show:button:clicked', (itemView) ->
  App.vent.trigger 'show:another:view:with:this:model', itemView.model

Спри тук. Моделът е стар модел и не се извозва.

Вместо това ще използвам кода по-долу:

@listenTo storiesView, 'itemview:show:button:clicked', (itemView) ->
  model = _.clone itemView.model
  App.vent.trigger 'show:another:view:with:this:model', model

Новият модел е напълно нов обект и няма нищо свързано с текущия изглед/модел/контролер.

person Billy Chan    schedule 05.03.2014
comment
Добре съм с повторното използване на модела, мисля, че е дори по-добре, тъй като не е нужно да разпределяте нова памет. Проблемът е атрибутът на колекцията вътре в модела. - person JayC; 06.03.2014