2012-04-09 4 views
20

Если вид Backbone View создает новые представления внутри метода render(), должны ли эти представления поддерживаться как элементы данных? Типичный метод визуализации выглядит следующим образом:Backbone.js - Должны ли вложенные представления поддерживать ссылки друг на друга?

render: function() { 
    var myView = new MyView({ model: values }); 
    $('div#value', this.el).append(myView.render().el); 
} 

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

Если вложенный вид должен быть изменен ... возможно, сильно, должен ли он быть просто (повторно) создан или должен быть изменен с помощью ссылки на данные?

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

На самом деле я не хочу, чтобы топ-старт бросал слушателей повсюду. И передавая ссылки на родительские представления и вызывается render() из дочернего объекта View, возникает утечка памяти, так как родитель создает новый дочерний вид, в то время как исходный дочерний элемент View поддерживает ссылку на родителя!

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

+1

Closures и объекты, которые не имеют живые ссылки или привязок где-нибудь на них (в основном ждут, чтобы быть мусора) не приведет к утечке памяти только потому, что у них есть ссылка на что-то существующее, по крайней мере, не в какой-либо схеме сбора мусора, о которой я знаю ... конечно, некоторые механизмы сбора мусора не будут хорошо работать с циклическими ссылками (без ручной обработки ссылок), но javascript использует Mark-and-Sweep и обрабатывает циклические ссылки просто отлично , Худшие проблемы AFAIK связаны с перекрестными ссылками между DOM и javascript «world», которые так говорят. – JayC

ответ

44

(предупреждение: мой ответ стал Т.Л., др трактата)

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

Большая проблема, связанная с обучением, состоит в том, что она настолько непригодна и может использоваться (и используется) многими способами, что трудно понять, как сделать что-то «правильно» или, по крайней мере, в хорошем смысле, вы начинаете. Существует не только один истинный способ использования магистрали, но ее гибкость делает ее потрясающей структурой практически для любого приложения, и, надеюсь, я могу помочь в предоставлении некоторых рекомендаций. (Я мог бы, вероятно, приложить «ИМО» к каждому предложению здесь).

Во-первых, мое понимание позвоночника рассматривает

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

Обычно у меня есть один или несколько представлений «root-level». Представления на уровне корня часто являются местом для инициализации, визуализации и хранения ссылок на дочерние представления, которые обрабатывают определенные части страницы. el уровня корневого уровня часто является «телом» или другим элементом высокого уровня в теле. В некоторых случаях представление на корневом уровне имеет собственный HTML-код для наблюдения и/или рендеринга. В других случаях представление на уровне корня может вообще не содержать el и просто управляет представлениями для детей. Я сохраняю ссылку на каждый вид корневого уровня (часто есть только один) в глобальном объекте пространства имен приложения.

В дополнение к представлениям «root-level» обычно существуют «дочерние представления». Представление child инициализируется и визуализируется «родительским» представлением, которое может представлять собой представление на уровне корня или другое дочернее представление. Родительские взгляды отвечают за инициализацию, визуализацию, скрытие, показ и/или уничтожение своих детей по мере необходимости. Иногда родительское представление может отслеживать переменное количество экземпляров дочернего представления (например, в PlaylistView есть N SongViews). Часто родители поддерживают ссылки на детей, но иногда это не нужно (подробнее об этом ниже).

В дополнение к парадигме «корневой уровень/родитель/ребенок» я склонен видеть, что виды вписываются в одну из двух категорий: (1) static: это означает, что после инициализации представления вид и его el stick вокруг, даже если в нем меняется материал; и (2) динамические, которые приходят и уходят, основываясь на различных событиях. Как правило, мои представления на уровне корня всегда статичны. Они также обычно соответствуют существующему элементу DOM, например, «body» или «my-div». Виды детей часто являются динамическими, но могут быть и статическими. (. Советы: используйте el: '#element-id' использовать существующий элемент DOM, как el при объявлении статического View Динамические представления обычно не уточняют существующие el, они используют tagNameid и className для описания элемента, что динамическое представление будет генерировать.)

Мнения, по существу, имеют 3 функции: (1) визуализировать себя и своих детей, когда им сообщают об этом их родителями или в ответ на события (или в случае представления на корневом уровне при инициализации маршрутизатором или «основным» 'функция и т. д.), (2) реагировать на события пользовательского интерфейса из элементов DOM в пределах их el (но не в пределах el любого детского представления) путем обновления моделей или коллекций или запуска пользовательских событий на основе базы и (3) наблюдать и реагировать на Магистраль (мод el, collection и т. д.), которые требуют, чтобы что-то отображалось или изменялось в пределах их el (но не внутри el любого дочернего представления.) Иногда полезно использовать трюк, что дочерние представления могут инициировать события на себе (this.trigger('customEvent')), что родитель вид может наблюдаться (childView.on('customEvent', this.handler, this)).

Для получения дополнительных интересных перспектив на схемах просмотра позвоночника см.: this и this.

В настоящее время в этом контексте, по вопросам

1) Страх сбора мусора, объем и памяти утечка

Если экземпляр вида ребенка в качестве локального вара в родителе Render (или другой) метод, а затем функция выходит за рамки, я могу понять ваш страх перед сбором мусора или что представление не сможет выполнить то, что ему нужно. Не нужно бояться сборщика мусора, просто зомби. Если ваше представление имеет какие-либо обработчики событий, независимо от того, объявлены ли обработчики событий пользовательского интерфейса в объявлении «события» или привязки к другим событиям объектов Backbone или другим прослушивателям событий на основе DOM, ваше представление не будет собираться с мусором, t больше ссылается на него - он все равно будет существовать в памяти и реагировать на события. С другой стороны, если в представлении нет обработчиков событий, то его единственным заданием является рендеринг элемента, поэтому кто заботится, будет ли объект javascript, который его отображает, - это, вероятно, будет сбор мусора, потому что он должен быть , См. this, для лучшего понимания сборки мусора js в целом и того, как она относится к Backbone.js.

Больше внимания вызывает Zombie views. Если виды должны быть удалены из DOM и по существу отброшены в какой-то момент вашего приложения, убедитесь, что они либо полностью удаляются, либо что родительские представления должны содержать ссылку на них и удалять их. И не создавайте и не создавайте и не заменяйте созданные ранее представления и не удаляйте их должным образом. Удаление выполняется путем вызова .remove() в представлении, а также отмена любых внешних событий Backbone, которые вы ранее связывали, используя on(...) с использованием off(...). Последние версии (1.0+) Backbone облегчают эту проблему, добавляя "listenTo" and "stopListening" methods к прототипу View. Понимать и использовать эти методы вместо включения/выключения, если вы динамически добавляете представления в DOM и из него. Совет. Настройка a hacky jquery "remove" event like this one может легко разрешить просмотр автономно удалять и очищать себя, когда их el удаляется из DOM (в случае, если в потоке вашего приложения нет события, которое может служить той же цели).

2) Должны ли представления детей поддерживаться как элементы данных родительских представлений?

Это зависит. Я не думаю, что родительские взгляды, осознающие их взгляды на детей в ограниченных целях, нарушают любые золотые принципы MVC. Иногда родитель, имеющий ссылки на определенные экземпляры дочерних представлений, является отличным способом управления дочерними представлениями, если/когда вам это нужно. Как я указывал, иногда родительские представления реагируют на события, которые требуют от них рендеринга, повторной рендеринга, скрыть или удалить их дочерние представления. Иногда они могут захотеть прослушать события, которые дочерние представления запускаются сами по себе. Родители, однако, не должны слишком вмешиваться во что-либо в своих детских взглядах, хотя, однако, el.

Тем не менее, не злоупотребляйте этими типами ссылок. Много раз вам не нужно будет использовать ссылки на детские представления, потому что дети могут позаботиться о себе. Как я уже упоминал, просмотры, однажды сделанные, должны только A) наблюдать за событиями пользовательского интерфейса внутри их el (но, как правило, не внутри любого дочернего вида el), и обновлять модели или коллекции или запускать события в ответ на эти события пользовательского интерфейса, или B) наблюдать за события от других магистральных объектов (обычно модели или коллекции или другие представления) и предпринимать действия (например, обновлять свои собственные элементы пользовательского интерфейса) в ответ. Во многих случаях представление может заботиться о себе и даже удалять себя. Если другой View или другой объект Backbone заботится о событии пользовательского интерфейса, которое происходит в вашем представлении, обновите модель или инициируйте событие на представлении и дайте им возможность наблюдать за ним. Аналогично, если что-то вне вашего представления требует обновленного рендеринга в вашем представлении, слушайте изменение модели или подождите соответствующего пользовательского события. Как общий принцип, взгляды должны быть блаженно не знакомы друг с другом, за исключением родителей, которые обращают внимание на своих детей, когда это имеет смысл.

3) Должны ли представления ребенка поддерживать ссылки на родительские представления?

Нет. Никогда. Я не могу придумать ни одного сценария, где вам нужно было бы что-то сделать с помощью ссылки на родителя, которая не может быть достигнута путем изменения модели, которую наблюдает родитель, или инициирования события (например, пользовательское событие, говорящее «hey, X произошло») на самом детском представлении или на другом базовом объекте «События». В Backbone я использую модели для представления как моих данных, так и моего состояния. Поэтому, если что-то происходит в представлении, которое меняет состояние моего приложения, я затем изменяю соответствующий атрибут состояния модели и позволяю другим представлениям (включая родителя) прислушиваться к автоматическому событию «change», если они им нравятся. Я также использую глобальный «вентиляционный» подобный шине объект (просто базовый объект javascript, который расширяет Backbone.Events) для запуска и прослушивания событий в приложении, а иногда я запускаю события непосредственно в представлениях, чтобы родительские объекты знали, что что-то произошло , Независимо от того, что работает, сохраняя при этом вашу архитектуру как можно распутанную.

4) Я не хочу, чтобы топ-старт бросал слушателей повсюду.

Ну, я думаю, одна хорошая вещь о позвоночнике является то, что вы не должны, но понимать, что шаблон Observer (т.е. событие & слушателей) и слабая связь лежит в основе аромата магистрального о MVC (обратите внимание, что каждое один класс Backbone расширяет события?), и большинство людей используют его соответствующим образом.

Рекомендации?

Я настоятельно рекомендую PeepCode tutorials, если вы не чувствуете, что находитесь на довольно продвинутом уровне. 12 баксов кусок, но вам нужно начать с первого или второго & третьим не будет очень полезно.

Также here's a nice overview.

Конец

+0

Спасибо. Это было невероятно полезно. – user941521

+0

Хорошо, @Ben R! +1: D –

+1

«Если у вашего представления есть какие-либо обработчики событий ... он не будет собираться с мусором, даже если у вас больше нет ссылки на него - он все равно будет существовать в памяти и отвечать на события». Что-то нужно иметь в виду при написании модульных тестов! –

Смежные вопросы