Los 8 errores más comunes que cometen los desarrolladores de Backbone.js
Publicado: 2022-03-11Backbone.js es un marco minimalista que tiene como objetivo proporcionar un conjunto simple de estructuras de datos y funciones que puede usar para crear el front-end de una aplicación web estructurada. Los componentes de Backbone.js listos para usar brindan un entorno intuitivo con el que quizás ya esté familiarizado al trabajar con modelos y vistas en el back-end. Los modelos y colecciones en Backbone.js son simples, pero vienen con algunas características muy útiles, como la opción de integrarlos fácilmente con las API REST JSON. Pero también son lo suficientemente flexibles para adaptarse a casi cualquier uso práctico.
En este tutorial de Backbone.js, veremos algunos errores comunes que a menudo cometen los desarrolladores independientes que intentan aprender Backbone.js y las formas de evitarlos.
Error #1: Ignorar las funcionalidades del Arsenal de Backbone.js
Backbone.js puede ser un marco minimalista, pero (junto con Underscore.js) proporciona una gran cantidad de características y funcionalidades que pueden cubrir fácilmente las necesidades más básicas y algunas de las críticas que surgen al desarrollar una aplicación web moderna. Un error común que los desarrolladores principiantes cometen a menudo es que toman Backbone.js como otro marco de cliente similar a MVC para la web. Aunque esta sección habla de algo muy obvio, cuando se trata de Backbone.js es un error realmente crítico no explorar el marco a fondo. El marco puede ser de tamaño pequeño, pero esto es lo que lo convierte en un gran candidato para esta exploración exhaustiva. Especialmente su código fuente pequeño y bien anotado.
Backbone.js proporciona el mínimo necesario para darle a su aplicación web la estructura de la que puede beneficiarse. Con su extensibilidad y gran cantidad de complementos, el aprendizaje de Backbone.js se puede utilizar para crear algunas aplicaciones web sorprendentes. Algunas de las características más obvias de Backbone.js se exponen a través de modelos, colecciones y vistas. Los componentes de enrutador e historial proporcionan un mecanismo simple pero elegante para admitir el enrutamiento del lado del cliente. Aunque Underscore.js es una dependencia de Backbone.js, está bastante bien integrado en el marco, ya que tanto los modelos como las colecciones se benefician mucho de este increíble cinturón de herramientas para JavaScript y también está disponible a su disposición.
El código fuente del marco está tan bien escrito y anotado que uno probablemente podría leerlo mientras toma una taza de café. Los principiantes pueden beneficiarse mucho al leer las anotaciones de origen, ya que pueden aprender mucho sobre cómo funciona el marco internamente y también adoptar un conjunto ordenado de mejores prácticas cuando se trata de JavaScript.
Error #2: Modificar DOM en Respuesta Directa a Eventos Arbitrarios
Algo que tendemos a hacer cuando empezamos a aprender Backbone.js es no hacer las cosas recomendadas por Backbone.js. Por ejemplo, tendemos a manejar eventos y ver actualizaciones como lo haríamos con jQuery en sitios web simples. Backbone.js está destinado a darle a su aplicación web una estructura rígida a través de una separación adecuada de las preocupaciones. Lo que solemos hacer con Backbone.js es actualizar una vista en respuesta a eventos DOM arbitrarios:
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { $(event.target).toggleClass('btn-play btn-pause') } }, // ... })
Esto es algo que debe evitarse a toda costa. Puede ser posible encontrar ejemplos oscuros donde esto pueda tener sentido; pero en la mayoría de los casos, hay formas mucho mejores de hacerlo. De hecho, una forma en la que posiblemente podría ejemplificar aquí es usar el modelo para rastrear el estado del reproductor de audio y usar esa información de estado para representar el botón (o más específicamente sus nombres de clase):
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { this.model.set('playing', !this.model.get('playing')) } }, initialize: function() { this.listenTo(this.model, 'change', this.render) this.render() }, // ... })
<button class=”btn btn-<%- playing ? 'pause' : 'play' %>”></button>
Puede haber situaciones excepcionales en las que la manipulación directa del DOM desde los controladores de eventos tenga sentido, pero el costo que implica administrar manipulaciones complejas del DOM desde los controladores de eventos casi nunca vale la pena. Esto es algo que Backbone.js pretende resolver. Usar Backbone.js para hacer algo como esto es un error.
Error n.º 3: subestimar el costo del renderizado
Dado que Backbone.js hace que sea muy fácil renderizar y volver a renderizar el DOM a voluntad o en respuesta a eventos, a menudo pasamos por alto el impacto que esto tiene en el rendimiento general de la aplicación web. Hay muchas formas en las que podemos terminar golpeando el método de renderizado en nuestras vistas. A menudo, esto puede no parecer mucho, ya que los navegadores web modernos se están convirtiendo en piezas de software de alto rendimiento. Pero a medida que crece la aplicación web y crece la cantidad de datos que maneja, la caída en el rendimiento se vuelve cada vez más evidente.
Podemos ver esto en acción a través de un ejemplo artificial en el que comenzamos con una pequeña colección de modelos y los representamos en una vista de lista:
var AudioPlayerPlaylist = Backbone.View.extend({ template: _.template('<ul> <% _.each(musics, function(m) { %> <li><%- m.title %></li> <% }) %> </ul>'), initialize: function() { this.listenTo(this.collection, 'add', this.render) }, // ... })
En este ejemplo de Backbone.js, volvemos a renderizar cada vez que se agrega un modelo a la colección. Esto funcionará bien. Sin embargo, dado que el evento "agregar" se activa cada vez que se agrega un modelo a la lista, imagine obtener una gran lista de modelos del servidor. El método de representación se invocará varias veces consecutivas, una vez para cada modelo en la respuesta del servidor. Un modelo lo suficientemente grande será suficiente para que su aplicación tartamudee y arruine la experiencia del usuario. A veces, una pequeña respuesta es suficiente, según la complejidad de la vista que se representa.
Una solución muy rápida a esto es simplemente no llamar al método de renderizado para cada modelo que se agrega. En situaciones como estas, los modelos se agregarán por lotes y, de hecho, puede hacer algo para que el método de renderizado se active solo cuando se invoque pero no se vuelva a invocar dentro de un período de tiempo específico. La dependencia de Backbone.js, Underscore.js, viene con una útil función de utilidad para esto: “_.debounce”. Todo lo que necesita para aprovechar esto es cambiar la línea JavaScript de enlace de eventos con esto:
this.listenTo(this.collection, 'add', _.debounce(_.bind(this.render), 128))
Esto hará que la devolución de llamada del evento se active cada vez que ocurra el evento "agregar", sin embargo, esperará 128 milisegundos desde el último evento antes de invocar realmente el método de procesamiento.
En la mayoría de los casos, esto se considerará una solución rápida. De hecho, hay formas más apropiadas de evitar la paliza de renderizado. Los desarrolladores detrás de Trello escribieron una vez una publicación de blog discutiendo sobre su experiencia y enfoque para mejorar el rendimiento de la representación al usar Backbone.js.
Error n.º 4: dejar a los oyentes de eventos atados más allá de su uso
Dejar los detectores de eventos no utilizados vinculados es probablemente algo que puede suceder independientemente del marco de JavaScript que use, o si usa alguno. Aunque Backbone.js hace que sea más fácil evitar este problema, es ciertamente un error dejar agujeros potenciales para pérdidas de memoria fáciles en su aplicación web. El componente "Evento" de Backbone.js es ciertamente una implementación bastante ordenada. Permite que los objetos de JavaScript implementen fácilmente funciones basadas en eventos. Dado que las vistas son donde suele ocurrir la mayor parte de nuestro consumo de eventos, es fácil cometer este error allí:
var AudioPlayerControl = Backbone.View.extend({ initialize: function() { this.model.on('change', _.bind(this.render, this)) // ... }, // ... })
La línea de vinculación de eventos en este fragmento de código no es muy diferente de la del primer ejemplo. Todo lo que hemos hecho aquí es que hemos cambiado "this.listenTo(this.model,...)" a "this.model.on(...)". Dado que estamos muy acostumbrados a la llamada ".on()" para el enlace de eventos a partir de nuestra experiencia con otros marcos y bibliotecas de JavaScript, cuando comenzamos a usar Backbone.js, a menudo tendemos a usar las llamadas ".on()" para enlazar eventos. Esto habría estado bien, solo si nos molestamos en llamar a ".off()" para desvincular los controladores de eventos cuando ya no sean necesarios. Pero rara vez hacemos eso, y termina siendo una fuente de fugas de memoria.

Backbone.js ofrece una forma sencilla de resolver este problema. Es a través del uso del método “object.listenTo()”. Esto permite que el objeto al que está llamando "listenTo ()" realice un seguimiento de los eventos que está escuchando, y también facilita la desvinculación de todos esos eventos a la vez. Las vistas, por ejemplo, dejan de escuchar automáticamente todos los eventos vinculados tan pronto como llamas a "eliminar ()".
Error #5: Crear vistas monolíticas
Si lo piensa, el minimalismo de Backbone.js proporciona una enorme cantidad de flexibilidad en la forma en que desea diseñar el front-end de su aplicación web. Dado que los modelos, las colecciones y las vistas son los componentes básicos de sus componentes, es esencial que los mantenga lo más ligeros y específicos posible. La mayoría de las veces, son las vistas las que terminan convirtiéndose en el aspecto más pesado de su aplicación web en términos de código. Pero es realmente importante que no termines haciendo vistas monolíticas gigantes que terminen tratando de hacer todo lo que tu aplicación tiene para ofrecer. En lugar de crear una vista gigante de "Reproductor de audio" con toda la lógica, divídala en varias vistas lógicas, como una vista para la lista de reproducción, una vista para los controles, una vista para el visualizador, etc. El tipo de granularidad que desea garantizar probablemente dependa de la aplicación que está tratando de construir.
Esto se debe a que con las vistas granulares, donde cada vista hace algo específico y lo hace bien, desarrollar una aplicación web con Backbone.js se convierte en un juego de niños. Su código debería ser más mantenible y fácil de ampliar o modificar en el futuro. Luego está el otro extremo, donde terminas exagerando. Las vistas de Backbone.js están diseñadas para que le resulte cómodo trabajar con un modelo o una colección, y esto probablemente pueda funcionar como una pista sobre cómo debe estructurar su aplicación. Ian Storm Taylor compartió algunas ideas valiosas en su blog que probablemente debería tener en cuenta al implementar vistas.
Error n.º 6: no darse cuenta de que Backbone.js se puede adaptar a API que no son RESTful
Backbone.js funciona con API RESTful basadas en JSON listas para usar. Todo lo que necesita para eso es jQuery (o algo que sea un reemplazo directo para él, como Zepto). Sin embargo, Backbone.js es extremadamente extensible. De hecho, Backbone.js se puede adaptar para usar otros tipos de API e incluso otro tipo de formatos de codificación.
El componente de Backbone.js que se ocupa de la interacción del front-end con los servicios de back-end es "Sync". Este componente expone una serie de atributos que puede anular fácilmente para personalizar la forma en que Backbone.js interactúa con los puntos finales de la API. De hecho, también es posible reemplazar el mecanismo de sincronización predeterminado con algo que no sea tan tradicional, por decir lo menos, como usar localStorage para conservar los datos, en lugar de los servicios de back-end.
Existen numerosos complementos que facilitan la personalización del comportamiento de sincronización de Backbone.js. Por ejemplo, un complemento llamado Backbone.dualStorage le permite usar tanto los servicios de back-end como localStorage para conservar los datos. Cuando su aplicación se desconecta, el complemento usa localStorage para seguir atendiendo solicitudes de datos almacenados en caché y realizar un seguimiento de los cambios que puede sincronizar con el servidor más adelante cuando esté en línea.
Aunque usar Backbone.js con un back-end que está diseñado para ser RESTful y ser compatible con él es más fácil de usar, no significa que Backbone.js sea todo lo que puede funcionar. Con algunos cambios en el mecanismo de sincronización predeterminado de Backbone.js, puede adaptarlo a una amplia gama de formatos de codificación y API de servicios de back-end.
Vale la pena mencionar que otras partes de Backbone.js también son flexibles y opcionales. Por ejemplo, no tiene que usar el motor de plantillas predeterminado que viene con Underscore.js. Ni siquiera tiene que usar el componente de vista de Backbone.js y puede reemplazarlo con algo completamente diferente si lo desea.
Error n.º 7: almacenar datos en vistas en lugar de en modelos
Un error que a menudo cometemos como principiantes en el aprendizaje de Backbone.js es almacenar datos directamente en las vistas como atributos. Estos datos pueden estar allí para rastrear algún estado o alguna selección de usuario. Esto es algo que debe evitarse.
var AudioPlayerVisualizer = Backbone.View.extend({ events: { 'click .btn-color': function(event) { this.colorHex = $(event.target).data('color-hex') this.render() } }, // ... })
Siempre puede crear algunos modelos y colecciones adicionales sin puntos finales. Estos pueden ayudarlo a almacenar datos que no necesariamente tienen que persistir en el back-end, o pueden ser de naturaleza temporal. Almacenarlos en modelos le brinda la ventaja de poder escuchar los cambios. La vista relevante, o incluso varias vistas, pueden observar estos modelos y volver a renderizarse según sea necesario.
Imagínese si realmente almacenara variables de seguimiento de estado en las vistas y tuviera que llamar al método de representación cada vez que las cambiara. Perder solo una llamada a este método de representación podría dejar su aplicación en un estado defectuoso, en términos de lo que el usuario está experimentando en la pantalla. Además, con vistas pequeñas, es posible que deba sincronizar estas variables de estado en varios objetos de vista y luego también debe llamar al método de representación en ellos.
Error #8: Usar jQuery “.on()” en lugar de eventos delegados
Backbone.js tiene, en mi opinión, una forma magnífica de manejar eventos DOM. No usarlo presenta un montón de desventajas. La función de vinculación de eventos “.on()” de jQuery puede parecer conveniente, pero a menudo resulta ser una molestia a largo plazo. Por ejemplo, cuando los elementos se separan del DOM, jQuery elimina automáticamente todos los controladores de eventos vinculados a los elementos mediante ".on()". Esto significa que cualquier evento DOM al que intente vincularse desde una vista deberá volver a vincularse si separa el elemento raíz del DOM y lo vuelve a vincular.
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function() { /* ... */ }, 'click .btn-prev': function() { /* ... */ }, 'click .btn-next': function() { /* ... */ }, 'click .btn-shuffle': function() { /* ... */ }, 'click .btn-repeat': function() { /* ... */ } }, // ... })
Cuando el elemento correspondiente a esta vista se vuelve a adjuntar al DOM, todo lo que tiene que hacer es llamar a "delegateEvents()" en la vista para vincular todos estos eventos.
Tenga en cuenta que es importante comprender cómo se vinculan estos eventos. En lugar de vincular el evento a los elementos especificados por el selector, Backbone.js vincula el controlador de eventos al elemento raíz de la vista. Esto funciona bien en casi todos los casos y, de hecho, funciona mejor para la mayoría de nuestras necesidades. Cambiar o reemplazar los elementos secundarios en el subárbol DOM de la vista no requiere que Backbone.js vincule cada evento nuevamente en los nuevos elementos. Los oyentes existentes simplemente siguen trabajando.
Sin embargo, esto impide que se escuchen ciertos eventos. Un ejemplo es donde es posible que desee escuchar eventos de desplazamiento en "ventana" o en un elemento desplazable secundario. En el caso de elementos secundarios, puede crear una subvista para ese elemento y manejar los eventos allí.
Conclusión
Backbone.js, al ser un marco muy compacto pero extensible, es una excelente opción para aplicaciones web que exigen una gran flexibilidad detrás de escena. A diferencia de marcos como Angular.js y Ember.js que siempre están ahí para decirle cómo hacer lo que quiere hacer, Backbone.js da un paso atrás, le brinda un poderoso conjunto de herramientas y le permite decidir cómo usar ellos. Espero que este tutorial de Backbone.js para principiantes lo ayude a evitar algunos de los errores de desarrollo comunes y a crear algo increíble con él.