Сводка: динамически устанавливать атрибуты представления с данными модели
http://jsfiddle.net/5wd0ma8b/
var View = Backbone.View.extend( {
attributes : function () {
return {
class : this.model.get( 'item_class' ),
id : this.model.get( 'item_id' )
};
}
} );
var item = new View( {
model : new Backbone.Model( {
item_class : "nice",
item_id : "id1"
} )
} );
В этом примере предполагается, что вы позволяете Backbone создавать за вас элемент DOM.
attributes
Метод вызывается после того, как свойства , передаваемые вид конструктора устанавливаются (в данном случае model
), что позволяет динамически устанавливать атрибуты с модельными данными , прежде чем создает Backbone el
.
В отличие от некоторых других ответов: не жестко кодирует значения атрибутов в классе представления, динамически устанавливает их из данных модели; не render()
дожидается установки attr vals; не устанавливает повторно значение attr при каждом вызове render()
; не устанавливает значения attr для элемента DOM без необходимости вручную.
Обратите внимание , что если установка класса при вызове Backbone.View.extend
или вид конструктора (например new Backbone.View
), вы должны использовать имя свойства DOM, className
, но если установить его с помощью attributes
хэш / метода (как в этом примере) , вы должны использовать имя атрибута, class
.
Начиная с Backbone 0.9.9:
При объявлении View ... 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
, рендеринг без обертки
В большинстве примеров, которые я видел, 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" );
}
http://jsfiddle.net/vQMa2/1/
Созданный элемент
Допустим, у вас нет существующего элемента, и вы разрешаете Backbone сгенерировать его за вас. Вы можете сделать что-то вроде этого (но, вероятно, лучше спроектировать вещи так, чтобы ваше представление не отвечало за знание чего-либо вне себя):
render : function () {
this.$el.html( "Some stuff" );
$( "#some-container" ).append( this.el );
}
http://jsfiddle.net/vQMa2/
Шаблоны
В моем случае я использую шаблоны, например:
<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
};
},
render : function {
var rendered_template = $( ... );
this.$el.empty().append( rendered_template.children() );
}
} );
attributes
, как и ряд других свойств Backbone, которые могут быть предоставлены как функция или некоторые другие тип значения. В этих случаях Backbone проверяет, является ли значение функцией, вызывает ее и использует возвращаемое значение.На ваш взгляд, просто сделайте что-нибудь вроде этого
var ItemView = Backbone.View.extend({ tagName: "div", // I know it's the default... render: function() { $(this.el).attr('id', 'id1').addClass('nice').html('Some Stuff'); } });
источник
Вы можете установить свойства
className
иid
для корневого элемента: http://documentcloud.github.com/backbone/#View-extendvar ItemView = Backbone.View.extend({ tagName: "div", // I know it's the default... className : 'nice', id : 'id1', render: function() { $(this.el).html("Some stuff"); } });
РЕДАКТИРОВАТЬ Включенный пример установки идентификатора на основе параметров конструктора
Если представления построены, как указано:
var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"});
Тогда значения можно было бы установить так:
// ... className: function(){ return this.options.item_class; }, id: function(){ return this.options.item_id; } // ...
источник
ItemView
будутid: 'id1'
. Это должно быть рассчитано во время выполнения на основеmodel.id
.Я знаю, что это старый вопрос, но добавлен для справки. Кажется, это проще в новых версиях магистрали. В Backbone 1.1 свойства id и className оцениваются в функции
ensureElement
(см. Из источника ) с использованием подчеркивания,_.result
означающего, что еслиclassName
илиid
является функцией, она будет вызываться, в противном случае будет использоваться ее значение.Таким образом, вы можете указать className прямо в конструкторе, указать другой параметр, который будет использоваться в className и т. Д. Множество опций
так что это должно работать
var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"}); var ItemView = Backbone.View.extend({ id: function() { return this.model.get('item_id'); }, className: function() { return this.model.get('item_class'); } });
источник
id: function() { return this.model.get('item_id'); })
Другие примеры не показывают, как на самом деле получить данные из модели. Чтобы динамически добавить идентификатор и класс из данных модели:
var ItemView = Backbone.View.extend({ tagName: "div", render: function() { this.id = this.model.get('item_id'); this.class = this.model.get('item_class'); $(this.el).attr('id',this.id).addClass(this.class).html('Some Stuff'); } });
источник
Вам нужно удалить tagName и объявить el.
«tagName» означает, что вы хотите, чтобы основа создавала элемент. Если элемент уже существует в DOM, вы можете указать el как:
el: $('#emotions'),
и позже:
render: function() { $(this.el).append(this.model.toJSON()); }
источник
Попробуйте назначить значения в методе инициализации, это будет напрямую динамически назначать идентификатор и класс атрибуту div.
var ItemView = Backbone.View.extend( { tagName : "div", id : '', class : '', initialize : function( options ) { if ( ! _.isUndefined( options ) ) { this.id = options.item_id; this.class= options.item_class; } }, render : function() { $( this.el ).html( this.template( "stuff goes here" ) ); } } );
источник
Вот минимальный способ динамически изменять класс элемента представления через модель и обновлять его при изменении модели.
var VMenuTabItem = Backbone.View.extend({ tagName: 'li', events: { 'click': 'onClick' }, initialize: function(options) { // auto render on change of the class. // Useful if parent view changes this model (e.g. via a collection) this.listenTo(this.model, 'change:active', this.render); }, render: function() { // toggle a class only if the attribute is set. this.$el.toggleClass('active', Boolean(this.model.get('active'))); this.$el.toggleClass('empty', Boolean(this.model.get('empty'))); return this; }, onClicked: function(e) { if (!this.model.get('empty')) { // optional: notify our parents of the click this.model.trigger('tab:click', this.model); // then update the model, which triggers a render. this.model.set({ active: true }); } } });
источник