Ответ 1
Сводка: динамически задавать атрибуты вида с данными модели
// View class with `attributes` method
var View = Backbone.View.extend( {
attributes : function () {
// Return model data
return {
class : this.model.get( 'item_class' ),
id : this.model.get( 'item_id' )
};
}
// attributes
} );
// Pass model to view constructor
var item = new View( {
model : new Backbone.Model( {
item_class : "nice",
item_id : "id1"
} )
} );
-
В этом примере предполагается, что вы позволяете Backbone генерировать элемент DOM для вас.
-
Метод
attributes
вызывается после того, как свойства, переданные конструктору вида, установлены (в данном случаеmodel
), что позволяет динамически устанавливать атрибуты с данными модели до создания Backboneel
. -
В отличие от некоторых других ответов: не содержит значения атрибутов жесткого кода в классе представления, динамически устанавливает их из данных модели; не дожидается, пока
render()
не установит attr vals; не многократно устанавливает attr vals при каждом вызовеrender()
; необязательно вручную устанавливает attr vals на элемент DOM. -
Обратите внимание, что если вы устанавливаете класс при вызове
Backbone.View.extend
или конструкторе представления (например,new Backbone.View
), вы должны использовать имя свойства DOM,className
, но если установить его с помощьюattributes
hash/method (как в этом примере), вы должны использовать имя атрибутаclass
. -
В соответствии с базой 0.9.9:
При объявлении представления...
el
,tagName
,id
иclassName
теперь могут быть определены как функции, если вы хотите, чтобы их значения определялись во время выполнения.Я упоминаю об этом в случае ситуации, когда это было бы полезно в качестве альтернативы использованию метода
attributes
, как показано на рисунке.
Использование существующего элемента
Если вы используете существующий элемент (например, передаете el
в конструктор вида)...
var item = new View( { el : some_el } );
... тогда attributes
не будет применяться к элементу. Если требуемые атрибуты еще не установлены в элементе или вы не хотите дублировать эти данные в классе вида и другом месте, то вы можете добавить метод initialize
к вашему конструктору вида, который применяет attributes
до el
. Что-то вроде этого (используя jQuery.attr
):
View.prototype.initialize = function ( options ) {
this.$el.attr( _.result( this, 'attributes' ) );
};
Использование el
, рендеринг, исключение оболочки
В большинстве примеров, которые я видел, view el служит бессмысленным элементом оболочки, внутри которого нужно вручную написать "семантический" код.
Нет причины view.el
должен быть "бессмысленным элементом оболочки". Фактически, это часто нарушает структуру DOM. Если класс представления представляет собой элемент <li>
, например, он должен быть отображен как <li>
- рендеринг его как <div>
или любой другой элемент разбил бы модель содержимого. Скорее всего, вы захотите сосредоточиться на правильной настройке своего элемента вида (используя такие свойства, как tagName
, className
и id
), а затем после этого передавая его содержимое.
Параметры того, как объекты просмотра Backbone взаимодействуют с DOM, широко открыты. Существует 2 основных исходных сценария:
-
Вы можете прикрепить существующий элемент DOM к представлению Backbone.
-
Вы можете разрешить Backbone создать новый элемент, который отключен от документа, а затем каким-то образом вставить его в документ.
Существуют различные способы сгенерировать контент для элемента (задайте литеральную строку, как в вашем примере, используйте библиотеку шаблонов, такую как Mustache, Handlebars и т.д.). Как вы должны использовать свойство el
представления, зависит от того, что вы делаете.
Существующий элемент
В примере рендеринга вы видите, что у вас есть существующий элемент, который вы назначаете для представления, хотя вы не показываете экземпляр представлений. Если этот случай и элемент уже находятся в документе, то вы можете сделать что-то вроде этого (обновите содержимое el
, но не изменяйте сам el
):
render : function () {
this.$el.html( "Some stuff" );
}
Сгенерированный элемент
Скажем, у вас нет существующего элемента, и вы разрешаете Backbone генерировать его для вас. Возможно, вам захочется сделать что-то подобное (но, скорее всего, лучше архитектовать вещи, чтобы ваше мнение не отвечало за знание чего-либо вне себя):
render : function () {
this.$el.html( "Some stuff" );
$( "#some-container" ).append( this.el );
}
Шаблоны
В моем случае я использую шаблоны, например:
<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->
Шаблон представляет полный вид. Другими словами, вокруг шаблона не будет обертки - div.player
будет корневым или внешним элементом моего представления.
Мой класс игрока будет выглядеть примерно так (с очень упрощенным примером render()
):
Backbone.View.extend( {
tagName : 'div',
className : 'player',
attributes : function () {
return {
id : "player-" + this.model.cid
};
},
// attributes
render : function {
var rendered_template = $( ... );
// Note that since the top level element in my template (and therefore
// in `rendered_template`) represents the same element as `this.el`, I'm
// extracting the content of `rendered_template` top level element and
// replacing the content of `this.el` with that.
this.$el.empty().append( rendered_template.children() );
}
} );