tutorial mario collection backbone backbone.js marionette

backbone.js - collection - marionette mario



Envoltorios extra en Backbone y Marionette (4)

ACTUALIZACIÓN: Marionette.Layout es una extensión de la vista Backbone, por lo que este es el comportamiento normal, consulte la documentación de backbone:

La propiedad "el" hace referencia al objeto DOM creado en el navegador. Cada vista Backbone.js tiene una propiedad "el", y si no está definida, Backbone.js construirá su propia propiedad, que es un elemento div vacío.

Así que mi respuesta anterior no tuvo nada que ver con tu problema, lo siento.

Actualizar:

Encontró un problema 546 en Backbone gitHub sobre este tema (que se cerró como wontfix), jashkenas publicó este comentario para explicar por qué no es fácil de implementar:

Una gran parte de la ventaja de usar las Vistas Backbone es el hecho de que tienen su elemento disponible en todo momento, independientemente de si una plantilla se ha renderizado (muchas vistas tienen múltiples plantillas), independientemente de si la vista está presente en el DOM o no.

Esto le permite crear y agregar vistas al DOM, renderizar más tarde, y asegurarse de que todos sus eventos estén enlazados correctamente (porque están delegados desde view.el).

Si puede idear una buena estrategia que permita que una vista tenga plantillas "completas" a la vez que conserva las características anteriores ... entonces hablemos de ello, pero debe permitir que exista el elemento raíz sin tener que mostrar el contenido de La plantilla (que puede depender de los datos que pueden no llegar hasta más tarde), y debe permitir que una vista tenga múltiples plantillas fácilmente.

Usando Backbone y Marionette, he creado un nuevo diseño que va a la división de contenido principal de mi página. El diseño se ve así:

<div id=''dash-sidebar''> <div id=''dash-profile''></div> <div id=''dash-nav''></div> </div> <div id=''dash-content''></div>

El problema es que cuando renderizo el diseño, Backbone lo envuelve automáticamente en un div antes de colocarlo en el div de contenido principal como este:

<div id=''main-content''> <div> <div id=''dash-sidebar''> <div id=''dash-profile''></div> <div id=''dash-nav''></div> </div> <div id=''dash-content''></div> </div> </div>

Sé que puedo cambiar el elemento con tagName, pero ¿es posible evitar la envoltura de la plantilla y simplemente insertarla directamente en la división de contenido principal en la página?


Cada vista de Backbone debe estar representada por un solo elemento. Su primer bloque HTML tiene dos elementos, por lo que no puede representarse con una vista sin antes envolverlo en un div exterior.

¿Podría refactorizar su diseño para incluir también el área de main-content ? Entonces el el de Layout correspondería a todo el div exterior.

Otra cosa a intentar sería utilizar el método setElement() Backbone.View para anular la creación del div externo e inyectar manualmente el HTML que desea para el elemento en una Vista. Algo como:

onRender: function() { this.setElement( /* the HTML you want for your layout */ ); }

Sin embargo, no estoy seguro de cómo funcionaría esto si pasara en HTML que tuviera dos elementos principales en lugar de uno solo.


Quería lograr casi lo mismo. Me gustaría tener todo el formato HTML en mis plantillas y dejar que Backbone haga el resto. Así que escribí el siguiente fragmento que elimina el ''div'' extra.

Primero, establezca el nombre de etiqueta en ''detectar'' y luego, después del primer procesamiento, detectará el nombre de etiqueta del primer elemento dentro de su vista. Obviamente, esto solo funciona cuando proporciona su propio envoltorio en su plantilla.

// Single table row inside tbody tableRowView = Backbone.Marionette.ItemView.extend({ tagName: ''detect'', template: function(data) { return Handlebars.templates[''tablerow/single''](data); }, onRender: function() { if (this.tagName == ''detect'') this.tagName = this.$el.children().first().prop(''tagName'').toLowerCase(); this.setElement( this.$el.children( this.tagName ) ); var $parent = this.$el.parent( this.tagName ); if ($parent.length) { this.$el.detach(); this.$el.insertAfter($parent); $parent.remove(); } }, modelEvents: { "change": "render" } });

Modelo:

<tr> <td>{{artist}}</td> <td>{{title}}</td> <td>{{length}}</td> </tr>

Sin embargo, solo he jugado un poco con él; si alguien ve algún problema que pueda causar este enfoque (rendimiento, memoria, zombies, etc.), estaría muy abierto a aprender sobre ellos.

Por cierto, esto probablemente podría empaquetarse fácilmente en un complemento.


EDIT3 : ¡Advertencia! Esta respuesta puede estar desactualizada. Recibí un comentario de que esta respuesta ya no funciona y no he tenido tiempo de investigar (personalmente no uso este método).

Me gusta usar Twitter / Bootstrap como mi biblioteca de UI y tuve algunos problemas con el estilo de la tabla debido al ajuste de etiquetas predeterminado (específicamente un <div> entre mi <tbody> y mi <tr> s).

Después de algunas excavaciones, encontré algo en los documentos de Marionette en la Region sobre cómo la View adjunta el el . Backbone construye el el desde varios atributos de View y mantiene el elemento construido actualizado para que pueda representarse en cualquier momento. Así que pensé, si view.el es el padre, ¿por qué no usar los contenidos HTML? Marionette también proporciona una forma de crear una Region personalizada.

Pude hacer que todo funcionara al crear una Region personalizada con una función de open anulada. De esa manera puedo especificar qué regiones quiero envolver con una etiqueta y las que no. En el siguiente fragmento de ejemplo, creo mi Region personalizada que no se NowrapRegion ( NowrapRegion ) y la uso en mi Layout ( MyLayout ) para mi <tbody> (las vistas que paso en mi programa real crean <tr> s).

var NowrapRegion = Marionette.Region.extend({ open: function(view){ this.$el.html(view.$el.html()); } }); var MyLayout = Marionette.Layout.extend({ template: templates.mylayout, regions: { foo: ''#foo'', columns: ''#columns'', //thead rows: { selector: ''#rows'', regionType: NowrapRegion } //tbody } });

¡AUGE! Envolviéndolo cuando lo quiero y ninguno cuando no.

EDITAR: Esto parece afectar los events aplicados en el nivel de *View . No lo he investigado todavía, pero ten en cuenta que no parece que se estén activando.

Si esta es la forma "correcta" de hacerlo o no, no estoy seguro. Me gustaría recibir cualquier comentario de @ derick-bailey si él ve esto.

EDIT2: @ chris-neale sugirió lo siguiente, no lo he verificado todavía pero parece correcto. ¡Gracias!

En lugar de copiar el html en la vista, el uso de un clon profundo en los nodos secundarios mantendrá eventos y datos.

var NowrapRegion = Marionette.Region.extend({ open: function(view){ view.$el.children().clone(true).appendTo(this.$el); } });