Con la incesante evolución de los navegadores web, cada vez resulta más evidente la necesidad de dedicar mayores esfuerzos de desarrollo a quien desde un principio ha debido considerarse protagonista de todo proyecto: el cliente.
No obstante, a diferencia del desarrollo de cara al servidor (server-side o back-end), cuidado con esmero durante muchos años a través de frameworks y herramientas que hicieran el trabajo más eficiente, escalable y robusto ante fallos, el desarrollo de cara al cliente (client-side o front-end) se ha visto relegado a un segundo plano, donde la estética y la experiencia del usuario resultaban méramente accesorias.
Esta tendencia está cambiando y lenguajes (como JavaScript) que antaño se empleaban para aplicar pequeñas pinceladas de funcionalidad a los sitios, ahora se ven saturadas ante la necesidad de crear con ellas aplicaciones completas, que se ejecutan en el navegador del usuario.
¿Qué es Backbone.js?
Se trata de un framework ligero para JavaScript que facilita la construcción de una potente interfaz de usuario para nuestra aplicación web, haciendo ésta más escalable, eficiente y robusta ante fallos mediante la aplicación de un patrón de arquitectura de software similar al MVC.
Backbone provee de medios para gestionar:
¿Cómo se estructura una interfaz con BackboneJS?
Existe mucha controversia en torno este tema, ya que como bien es sabido JavaScript podría funcionar perfectamente con todo el código en un único fichero. Sin embargo, no es esa la filosofía que se pretende seguir, sino más bien la de un código correctamente organizado y fácil de mantener y escalar. Para su compactación, ya existen numerosas herramientas que nos ahorrarán tiempo y esfuerzo.
Propuesta de organización
Siguiendo los consejos de la gente de Bocoup, esta podría ser una buena forma de estructurar la interfaz de nuestro proyecto con BackboneJS. Supongamos una pequeña aplicación de chat, donde tenemos usuarios y mensajes (los modelos) y podemos chatear o gestionar los contactos (vistas).
|- HTML/
|- CSS/
|- JS/
|- core.js
|- libs/
|- jquery.js
|- underscore.js
|- backbone.js
|- views/
|- chat.js
|- contact.js
|- models/
|- user.js
|- message.js
De esta forma, podremos atacar de forma más o menos sencilla y directa aquella funcionalidad o ámbito de la interfaz en la que queramos aplicar cambios.
Es importante aclarar que el orden de la carga de los diferentes ficheros desde el navegador no es siempre arbitrario, teniendo que establecer su órden de la siguiente manera:
Bibliotecas (el orden importa)
Un ejemplo sencillo con BBJS
El núcleo de la aplicación: core.js
Este fichero hace de nexo de unión de vistas y modelos. Define un espacio de nombres dentro del que trabajará nuestra aplicación (evitando así la contaminación del espacio de nombres con otras aplicaciones, e incluso entre distintas vistas y modelos).
Aunque el núcleo podría ser simplemente algo de este tipo:
No obstante, esto provocaría que cada vez que queramos agregar un nuevo modelo, debamos modificar este core.js, lo cual no es muy conveniente para grandes proyectos. Además, en el momento en que se definiera algo del tipo chat.friend = null, dicho modelo dejaría de ser usable. Para evitar esto, se emplea una técnica denominada “memoizing” para crear una función reutilizable que creará un objeto compartido y lo recordará internamente asociado a una clave, tal que
Un ejemplo de vista básica
Un ejemplo muy simple de una vista lo tenemos en el siguiente fragmento de código (inicialmente extraido de la web de Thomas Davis y hechas unas pequeñas modificaciones).
De esta forma, la vista llamada “AppView” define un entorno del árbol DOM sobre el que actúa (“el”), establece unos objetos iniciales (en “initialize”), define unos eventos (“events”), y unas funciones a ser llamadas por los eventos o por cualquier otra acción de la vista.
Hay muchas propiedades más que se pueden definir en una vista y que no se detallarán aquí. Para más información, consultar la web del proyecto en Github.
Un modelo para la vista anterior
El modelo cargado por la anterior vista es tan sencillo como lo siguiente:
De nuevo, para los modelos pueden ser definidos más listeners y funcionalidades que harían más largo este artículo, si cabe.
El ejemplo completo en funcionamiento se puede ver en la siguiente dirección.
¡BackboneJS es mucho más!
Si siguiera ahondando en las ventajas que aporta BackboneJS a nuestros desarrollos, no acabaría este artículo nunca. Por ello, animo a todo aquel interesado en el tema que visite el proyecto en Github, donde encontrará una extensa documentación acerca de cada una de las característica que este framework ofrece.
Para más ejemplos y referencias de uso de BackBone.js, ver aquí.
Sérgio Almécija
No obstante, a diferencia del desarrollo de cara al servidor (server-side o back-end), cuidado con esmero durante muchos años a través de frameworks y herramientas que hicieran el trabajo más eficiente, escalable y robusto ante fallos, el desarrollo de cara al cliente (client-side o front-end) se ha visto relegado a un segundo plano, donde la estética y la experiencia del usuario resultaban méramente accesorias.
Esta tendencia está cambiando y lenguajes (como JavaScript) que antaño se empleaban para aplicar pequeñas pinceladas de funcionalidad a los sitios, ahora se ven saturadas ante la necesidad de crear con ellas aplicaciones completas, que se ejecutan en el navegador del usuario.
¿Qué es Backbone.js?
Se trata de un framework ligero para JavaScript que facilita la construcción de una potente interfaz de usuario para nuestra aplicación web, haciendo ésta más escalable, eficiente y robusta ante fallos mediante la aplicación de un patrón de arquitectura de software similar al MVC.
Backbone provee de medios para gestionar:
- Modelos: Gestionan los datos con los que trabaja la aplicación, permitiendo su carga, edición y almacenado posterior en el servidor. Además, permiten definir en ellos toda la funcionalidad asociada a la gestión de estos datos.
- Colecciones: Son conjuntos de instancias de un modelo, que podemos manipular para mantener en el cliente la infomación necesaria sin tener que estar contínuamente cargándola desde el servidor.
- Vistas: En backboneJS, las vistas no determinan la estética de la aplicación, sino que se limitan a ser una vía de organización para la interfaz. Definiendo distintas vistas para diferentes lógicas de la aplicación, evitaremos interminables ficheros de código desestructurado, donde cualquier mínimo cambio puede suponer un gran esfuerzo.
¿Cómo se estructura una interfaz con BackboneJS?
Existe mucha controversia en torno este tema, ya que como bien es sabido JavaScript podría funcionar perfectamente con todo el código en un único fichero. Sin embargo, no es esa la filosofía que se pretende seguir, sino más bien la de un código correctamente organizado y fácil de mantener y escalar. Para su compactación, ya existen numerosas herramientas que nos ahorrarán tiempo y esfuerzo.
Propuesta de organización
Siguiendo los consejos de la gente de Bocoup, esta podría ser una buena forma de estructurar la interfaz de nuestro proyecto con BackboneJS. Supongamos una pequeña aplicación de chat, donde tenemos usuarios y mensajes (los modelos) y podemos chatear o gestionar los contactos (vistas).
|- HTML/
|- CSS/
|- JS/
|- core.js
|- libs/
|- jquery.js
|- underscore.js
|- backbone.js
|- views/
|- chat.js
|- contact.js
|- models/
|- user.js
|- message.js
De esta forma, podremos atacar de forma más o menos sencilla y directa aquella funcionalidad o ámbito de la interfaz en la que queramos aplicar cambios.
Es importante aclarar que el orden de la carga de los diferentes ficheros desde el navegador no es siempre arbitrario, teniendo que establecer su órden de la siguiente manera:
Bibliotecas (el orden importa)
- jquery.js
- underscore.js
- backbone.js
- <Resto de bibliotecas que queramos>
- core.js
- vistas y modelos (el orden entre ellos no importa)
Un ejemplo sencillo con BBJS
El núcleo de la aplicación: core.js
Este fichero hace de nexo de unión de vistas y modelos. Define un espacio de nombres dentro del que trabajará nuestra aplicación (evitando así la contaminación del espacio de nombres con otras aplicaciones, e incluso entre distintas vistas y modelos).
Aunque el núcleo podría ser simplemente algo de este tipo:
var chat = {
friend: { Views: {} },
message: { Views: {} }
};
No obstante, esto provocaría que cada vez que queramos agregar un nuevo modelo, debamos modificar este core.js, lo cual no es muy conveniente para grandes proyectos. Además, en el momento en que se definiera algo del tipo chat.friend = null, dicho modelo dejaría de ser usable. Para evitar esto, se emplea una técnica denominada “memoizing” para crear una función reutilizable que creará un objeto compartido y lo recordará internamente asociado a una clave, tal que
var chat = {
// Create this closure to contain the cached modules
module: function() {
// Internal module cache.
var modules = {};
// Create a new module reference scaffold or
//load an existing module.
return function(name) {
// If this module has already been created, return it.
if (modules[name]) {
return modules[name];
}
// Create a module and save it under this name
return modules[name] = { Views: {} };
};
}()
};
Un ejemplo de vista básica
Un ejemplo muy simple de una vista lo tenemos en el siguiente fragmento de código (inicialmente extraido de la web de Thomas Davis y hechas unas pequeñas modificaciones).
(function ($) {
//Dependencias: modelos que empleará esta vista
var Friend = chat.module("friend");
AppView = Backbone.View.extend({
el: $("body"),
initialize: function () {
//Se crea una colección inicial vacía de objetos
//“friend”
this.friends = new Friend.List( null, { view: this });
},
//Todos los eventos están agrupados en el mismo sitio
//y su ámbito se restringe al de la vista (definido
//por el atributo “el”).
events: {
"click #add-friend": "showPrompt",
},
//Funciones de la vista:
showPrompt: function () {
var friend_name = prompt("Who is your friend?");
var friend_model = new Friend.Model({ name: friend_name });
this.friends.add( friend_model );
},
addFriendLi: function (model) {
//The parameter passed is a reference
//to the model that was added
$("#friends-list").append("<li>"+model.get('name')+"</li>");
//Use .get to receive attributes of the model
}
});
//Lanzamiento de la vista para su ejecución
var appview = new AppView;
})(jQuery);
De esta forma, la vista llamada “AppView” define un entorno del árbol DOM sobre el que actúa (“el”), establece unos objetos iniciales (en “initialize”), define unos eventos (“events”), y unas funciones a ser llamadas por los eventos o por cualquier otra acción de la vista.
Hay muchas propiedades más que se pueden definir en una vista y que no se detallarán aquí. Para más información, consultar la web del proyecto en Github.
Un modelo para la vista anterior
El modelo cargado por la anterior vista es tan sencillo como lo siguiente:
(function (Friend) {
//Create a model to hold friend atribute
Friend.Model = Backbone.Model.extend({
name: null
});
//This is our Friends collection and holds
//our Friend models
Friend.List = Backbone.Collection.extend({
model: Friend.Model,
initialize: function (models, options) {
this.bind("add", options.view.addFriendLi);
//Listen for new additions to the collection
//and call a view function if so
}
});
})(chat.module("friend"));
El ejemplo completo en funcionamiento se puede ver en la siguiente dirección.
¡BackboneJS es mucho más!
Si siguiera ahondando en las ventajas que aporta BackboneJS a nuestros desarrollos, no acabaría este artículo nunca. Por ello, animo a todo aquel interesado en el tema que visite el proyecto en Github, donde encontrará una extensa documentación acerca de cada una de las característica que este framework ofrece.
Para más ejemplos y referencias de uso de BackBone.js, ver aquí.
Sérgio Almécija
muchas gracias, ya estaba que le echaba basura pero ahora entiendo muchas cosas mejor.
ResponderEliminar