позвоночник.Яш структурирование вложенных представлений и моделей
через хребет.js:
у меня есть модель верхнего уровня, которая содержит 2 атрибута и 2 вложенные модели, ModelB и ModelC. Модельв и модельки по 2 атрибуты следующим образом:
ModelA
attributeA1
attributeA2
ModelB
attributeB1
attributeB2
ModelC
attributeC1
attributeC2
существует ViewA для ModelA и ViewB для ModelB. Функция рендеринга ViewA помещает новый div на тело, в то время как рендеринг ViewB создает h1. Инициализация ViewA вызывает рендер ViewB для вставки этого h1 в новый div. Обоснование этого разделения заключается в том, что h1 может измениться и потребовать повторного рендеринга независимо от ViewA.
ViewA
initialise:
//call ViewA's own render function
this.render()
//call ViewB's render function that further modifies the $("#new") div created earlier.
$("#new").append(ViewB.render().el)
//ViewA's own render function
render: //place <div id="new"></div> onto 'body'
ViewB
render: //create a <h1></h1>
funcB1: //can this access it's parent ModelA's attributes and other objects?
Q1: ViewB имеет функцию funcB1. Может ли эта функция получить доступ к атрибутам родительской модели? Атрибуты, такие как attributeA1, или даже attributeC1 (который был бы родным братом/двоюродным братом)?
Q2: как дальнейшее расширение до Q1, может ли funcB1 получить доступ к элементам DOM, связанным с ViewA? (в этом примере, #new div?)
Q3: в общем, как я могу определить ассоциации между представлениями и Модели, как описано выше, чтобы все связывалось правильно?
Я понимаю, что этот вопрос несколько абстрактен, но любой ценит любую помощь или рекомендации.
5 ответов:
чтобы иметь возможность достигать атрибутов на связанных моделях, модель должна иметь какие-то знания о том, с какими моделями она связана. Позвоночник.js не имеет неявного отношения к отношениям или вложенности, что означает, что вы должны сами убедиться, что модели имеют знания друг о друге. Чтобы ответить на ваши вопросы, один из способов сделать это-убедиться, что каждая дочерняя модель имеет атрибут "родитель". Таким образом, вы можете пройти вложенность сначала до родителя, а затем до любых братьев и сестер, которые вы знаю.
чтобы быть более конкретным с вашими вопросами. При инициализации modelA вы, вероятно, создаете modelB и modelC, я бы предложил установить ссылку на родительскую модель при этом, например:
ModelA = Backbone.Model.extend({ initialize: function(){ this.modelB = new modelB(); this.modelB.parent = this; this.modelC = new modelC(); this.modelC.parent = this; } }
таким образом, вы можете достичь родительской модели в любой функции, модели детей, называя это.родитель.
Что касается ваших представлений, при выполнении вложенных базовых представлений мне проще позволить каждому представлению представлять один HTML-тег, используя опцию tagName вид. Я бы написал ваши взгляды так:
ViewA = Backbone.View.extend({ tagName: "div", id: "new", initialize: function(){ this.viewB = new ViewB(); this.viewB.parentView = this; $(this.el).append(this.viewB.el); } }); ViewB = Backbone.View.extend({ tagName: "h1", render: function(){ $(this.el).html("Header text"); // or use this.options.headerText or equivalent }, funcB1: function(){ this.model.parent.doSomethingOnParent(); this.model.parent.modelC.doSomethingOnSibling(); $(this.parentView.el).shakeViolently(); } });
затем в вашем коде инициализации приложения (например, в вашем контроллере) я бы инициировал ViewA и поместил его элемент внутри элемента body.
общий ответ на вопрос "Могу ли я" всегда "да, пока вы готовы написать код."За основу-обеспечить строгое разделение модели и представления. Если B1 имеет ссылку на A1, а A1 имеет ссылку на C1, то вы полностью способны создавать методы и устанавливать правила, с помощью которых B1 может изменять A1 и C1 и т. д.
представления должны быть настроены для получения событий CRUD от их соответствующих моделей. Если пользователь что-то делает с B1view, который изменяет B1model, и B1model в свою очередь изменяет A1model, то A1model должен генерировать событие, которое a1view получает и вызывает повторную визуализацию A1view, и так далее. Это должно произойти как по волшебству. (На практике требуется некоторое время, чтобы правильно использовать магию, но я обнаружил, что позвоночник действительно силен. И BackboneRelational помогает с такими вещами, как то, что вы описываете здесь.)
вышеуказанное решение находится на правильном пути, но есть некоторые проблемы.
initialize: function(){ this.viewB = new ViewB(); this.viewB.parentView = this; $(this.el).append(this.viewB.el); }
в основном, модель toJSON () теперь возвращает устаревшие данные. Я выложил решение этой проблемы костяк.плагин JS. Вы можете использовать его.
вы можете использовать некоторые расширения, Backbone-Forms https://github.com/powmedia/backbone-forms например. Чтобы следовать вашему варианту использования, определите схему следующим образом:
var ModelB = Backbone.Model.extend({ schema: { attributeB1: 'Text', attributeB2: 'Text' } }); var ModelC = Backbone.Model.extend({ schema: { attributeC: 'Text', } }); var ModelA = Backbone.Model.extend({ schema: { attributeA1: 'Text', attributeA2: 'Text', refToModelB: { type: 'NestedModel', model: ModelB, template: 'templateB' }, refToModelC: { type: 'NestedModel', model: ModelC, template: 'templateC' } } });
посмотрите на https://github.com/powmedia/backbone-forms#customising-templates для частичных шаблонов.
важные части здесь
type: 'NestedModel'
иtemplate: 'templateXXX'
.этот плагин имеет некоторые ограничения, но вы можете посмотреть на другие по https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources.
есть магистральный плагин Backbone-relational.JS код, который обеспечивает один-к-одному, один-ко-многим и многие-к-одному отношения между моделями для позвоночника.
Я думаю, что это JS будет выполнять ваши потребности. Вист BackboneRelational для получения дополнительной документации.