Resumen: establecer atributos de vista de forma dinámica con datos del modelo
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"
} )
} );
Este ejemplo asume que está permitiendo que Backbone genere un elemento DOM por usted.
El attributes
método se llama después de que se establecen las propiedades pasadas al constructor de la vista (en este caso, model
), lo que le permite establecer dinámicamente los atributos con los datos del modelo antes de que Backbone cree el
.
En contraste con algunas de las otras respuestas: no codifica los valores de los atributos en la clase de vista, los establece dinámicamente a partir de los datos del modelo; no espera hasta render()
establecer attr vals; no establece repetidamente attr vals en cada llamada a render()
; no establece innecesariamente manualmente los valores de atributo en el elemento DOM.
Tenga en cuenta que si el establecimiento de la clase cuando se llama Backbone.View.extend
o una vista de constructor (por ejemplo new Backbone.View
), usted tiene que utilizar el nombre de la propiedad DOM, className
pero si su creación a través de la attributes
almohadilla / método (como en este ejemplo) tiene que usar el nombre del atributo, class
.
A partir de Backbone 0.9.9:
Cuando se declara una vista ... el
, tagName
, id
y className
ahora puede definirse como funciones, si quieres sus valores que deben determinarse en tiempo de ejecución.
Menciono esto en caso de que exista una situación en la que sea útil como alternativa al uso de un attributes
método como se ilustra.
Usando un elemento existente
Si está utilizando un elemento existente (por ejemplo, pasando el
al constructor de la vista) ...
var item = new View( { el : some_el } );
... entonces attributes
no se aplicará al elemento. Si los atributos deseados aún no están configurados en el elemento, o no desea duplicar esos datos en su clase de vista y en otra ubicación, entonces puede agregar un initialize
método a su constructor de vista que se aplique attributes
a el
. Algo como esto (usando jQuery.attr
):
View.prototype.initialize = function ( options ) {
this.$el.attr( _.result( this, 'attributes' ) );
};
Uso de el
, renderizado, evitando la envoltura
En la mayoría de los ejemplos que he visto, el el de la vista sirve como un elemento contenedor sin sentido dentro del cual uno tiene que escribir manualmente el código 'semántico'.
No hay ninguna razón view.el
para que sea "un elemento contenedor sin sentido". De hecho, eso a menudo rompería la estructura DOM. Si una clase de vista representa un <li>
elemento, por ejemplo, necesita ser renderizado como un <li>
- renderizarlo como un <div>
o cualquier otro elemento rompería el modelo de contenido. Es probable que desea enfocar correctamente la configuración de elemento de la vista (utilizando propiedades como tagName
, className
y id
) y luego emitir su contenido a partir de entonces.
Las opciones sobre cómo hacer que los objetos de la vista Backbone interactúen con el DOM están abiertas. Hay 2 escenarios iniciales básicos:
Puede adjuntar un elemento DOM existente a una vista Backbone.
Puede permitir que Backbone cree un nuevo elemento que esté desconectado del documento y luego, de alguna manera, insertarlo en el documento.
Hay varias formas de generar el contenido del elemento (establezca una cadena literal, como en su ejemplo; use una biblioteca de plantillas como Moustache, Handlebars, etc.). La forma en que debe usar la el
propiedad de la vista depende de lo que esté haciendo.
Elemento existente
Su ejemplo de representación sugiere que tiene un elemento existente que está asignando a la vista, aunque no muestra la instanciación de las vistas. Si ese es el caso, y el elemento ya está en el documento, entonces es posible que desee hacer algo como esto (actualice el contenido de el
, pero no se altere el
):
render : function () {
this.$el.html( "Some stuff" );
}
http://jsfiddle.net/vQMa2/1/
Elemento generado
Digamos que no tiene un elemento existente y permite que Backbone genere uno por usted. Es posible que desee hacer algo como esto (pero probablemente sea mejor diseñar las cosas para que su vista no sea responsable de saber nada fuera de sí mismo):
render : function () {
this.$el.html( "Some stuff" );
$( "#some-container" ).append( this.el );
}
http://jsfiddle.net/vQMa2/
Plantillas
En mi caso, estoy usando plantillas, por ejemplo:
<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->
La plantilla representa la vista completa. En otras palabras, no habrá ningún envoltorio alrededor de la plantilla:div.player
será la raíz o el elemento más externo de mi vista.
Mi clase de jugador se verá así (con un ejemplo muy simplificado de 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
, como una serie de otras propiedades de Backbone que se pueden suministrar como una función o alguna otra. tipo de valor. En esos casos, Backbone comprueba si el valor es una función, lo llama y usa el valor de retorno.En tu opinión, haz algo como esto
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'); } });
fuente
Puede configurar las propiedades
className
yid
en el elemento raíz: 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"); } });
EDITAR Ejemplo incluido de configuración de id basado en parámetros de constructor
Si las vistas se construyen como se menciona:
var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"});
Entonces, los valores podrían establecerse de esta manera:
// ... className: function(){ return this.options.item_class; }, id: function(){ return this.options.item_id; } // ...
fuente
ItemView
habrán hechoid: 'id1'
. Esto debe calcularse en tiempo de ejecución basado en elmodel.id
.Sé que es una pregunta antigua, pero agregada como referencia. Esto parece ser más fácil en las nuevas versiones de backbone. En Backbone 1.1, las propiedades id y className se evalúan en la función
ensureElement
(ver de la fuente ) usando un subrayado que_.result
significa que siclassName
oid
es una función, se llamará, de lo contrario, se usará su valor.Entonces podría dar className directamente en el constructor, dar otro parámetro que se usaría en className, etc ... Un montón de opciones
entonces esto debería funcionar
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'); } });
fuente
id: function() { return this.model.get('item_id'); })
Los otros ejemplos no muestran cómo tomar realmente los datos del modelo. Para agregar dinámicamente id y clase a partir de los datos del modelo:
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'); } });
fuente
Necesita eliminar tagName y declarar un el.
'tagName' significa que desea que la red troncal cree un elemento. Si el elemento ya existe en el DOM, puede especificar un el como:
el: $('#emotions'),
y después:
render: function() { $(this.el).append(this.model.toJSON()); }
fuente
Intente asignar los valores en el método initialize, esto asignará directamente id y class al atributo div de forma dinámica.
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" ) ); } } );
fuente
Aquí hay una forma mínima de cambiar la clase del elemento de la vista dinámicamente a través de un modelo y actualizarlo en los cambios del modelo.
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 }); } } });
fuente