Han pasado unos pocos meses sin nuevas publicaciones y qué mejor forma de volver al ruedo que con un tutorial sobre una de esas tecnologías que están en pleno auge y que están cambiando la forma de desarrollar las nuevas aplicaciones web. Vamos con Backbone y javascript.

Autor:

Intentando mejorar cada día en este mundo tan cambiante de la programación. Sígueme en Twitter o en GitHub. Actualmente estoy disponible para contratar.

Cada vez más, las aplicaciones web tienden a dejar de lado el antigüo modelo de “hago click y espero a que cargue una nueva página” para enfocarse en un modelo más interactivo e instantáneo, en el que las acciones de usuario tienen una respuesta inmediata, imitando así las aplicaciones de escritorio. Como sabrás, para conseguir esto, se necesita delegar el control de nuestra aplicación a Javascript.

En un principio, la simple idea de gestionar una aplicación completa en Javascript nos puede desbordar, pero no te preocupes, ya que existen múltiples frameworks que nos ayudan a llevar a cabo esta tarea, y uno de ellos es Backbone.js.

¿Qué puedo hacer con Backbone.js?

Backbone te permite estructurar tu aplicación mediante modelos (que es la forma de organizar tus datos en objetos), colecciones y vistas, y conecta todo con tu API del servidor a través de una interfaz JSON. Tambien te permite tener vinculado un modelo con su vista de forma sincronizada, así, si cambia una propiedad del modelo, cambiará también su representación en la interfaz.

Eso… ¡y muchas cosas más! Enumero ahora las características más importantes poniendo ejemplos para cada una de ellas.

Backbone.Model

Es el núcleo del framework, ya que es la forma que tienes de organizar los datos con los que va a trabajar tu aplicación. Un modelo puede representar, por ejemplo, la información de una tarea, con sus atributos y métodos, y se define de la siguiente forma:

var Task = Backbone.Model.extend({
    defaults: {
        title: 'Tarea sin título',
        status: 'Open'
    },
    close: function(){
        this.set('status', 'Closed');
    },
    open: function(){
         this.set('status', 'Open');
    }
});

window.mytask = new Task({
    'title': 'Ir al super',
    'text': 'Comprar leche y patatas'
});

En el ejemplo anterior creamos el modelo para una tarea, que tiene dos atributos por defecto (title y status) y dos métodos (close y open). Al crear una instancia de un modelo, le pasamos los valores de inicialización en el constructor, tal como se muestra en el ejemplo.

Para acceder a los valores de los atributos del modelo, no se hace de forma directa, si no que se hace a través del método get():

save

Llama a este método cuando desees guardar el estado actual del modelo en la base de datos. Si es un modelo nuevo, es decir, no se había creado antes en la base de datos, el método enviará una llamada tipo POST a la url encargada de gestionar dicho modelo. En el caso de que el modelo ya exista, se hará una llamada de tipo PUT

var Task = Backbone.Model.extend({
    urlRoot: '/tasks'
});
window.mytask = new Task({title: 'Ir al super', 'text': 'Comprar leche y patatas'});
window.mytask.save();

Hace una llamada AJAX de tipo POST al servidor.

destroy

Envía una llamada AJAX de tipo DELETE al servidor para eliminar el modelo de la base de datos y lanza el evento destroy a través de todo el modelo y colecciones para mantenerlos sincronizados.

validate

Necesitas sobreescribir este método en el modelo si necesitas validar los datos antes de hacer un set o un save. La función recibe por parámetro los nuevos valores de los atributos, y si los datos son correctos, la función no devolverá nada, en caso contrario, puede devolver una cadena de texto con el error, un número de error, o lo que quieras y no se continuará con la ejecución del set o save.

var Task = Backbone.Model.extend({
    validate: function(attrs){
        if(attrs.status !== 'Open' || attrs.status !== 'Closed'){
            return 'Invalid task status!';
        }
    }
});

Backbone.Collection

Una colección es un conjunto ordenados de modelos sobre la que se pueden añadir listeners para eventos como change, add, remove o ejecutar métodos como fetch, que carga la colección desde el servidor. Para definir una colección, se usa igualmente el método extend pero de la clase Backbone.Collection:

var TaskList = Backbone.Collection.extend({
    model: Task,
    url: '/tasklist',
    closed: function(){
        return this.filter(function(task){ return task.get('status') == 'Closed' });
    }
});
window.taskList = new TaskList();

En el código anterior, se crea un colección para modelos de tipo Task, cuya url para manejar la persistencia es /tasklist. Además añade un método propio para filtrar la colección por las tareas cuyo estado es ‘Closed’.

add

Añade un modelo o un array de modelos a la colección. Si has especificado el atributo model puedes directamente añadir los atributos de cada objeto.

Como ves, no es necesario que crees el objeto antes de añadirlo, puedes directamente especificar sus atributos

remove

Elimina un modelo de la colección. Si deseas eliminar todo rastro de dicho modelo, esta es la forma recomendada:

Task.bind("remove", function(){
    this.destroy();
}
var task = new Task();
taskList.add(task);
taskList.remove(task);

Al llamar al método remove de la colección se lanza el evento remove en el modelo sobre que se está eliminando, y luego, desde dicho modelo llamamos al método destroy para que se borre tambien del server (si es lo que queremos).

fetch

Este método se encarga de traer el conjunto de modelos del servidor y cargarlos en la colección, reseteándola. El server debe de encargarse de devolver la colección de los modelos en formato JSON, si estás trabajando sobre una API del servidor antigüa y no puedes generar dicha respuesta, te interesará sobreescribir el método parse

parse

Este método es llamado por Backbone cuando esta necesita convertir una respuesta del servidor en un conjunto de modelos. Por lo tanto, es útil sobreescribir este método si no estás trabjando con la API que Backbone espera por defecto.

Por ejemplo, imagina que el server en lugar de devolver directamente el array con los modelos, devuelve un objeto que contiene más información. Puedes sobreescribir el método para pasarle a backbone cuales son los datos que debe usar.

var TaskList = Backbone.Collection.extend({
    parse: function(response){
        //response es el objeto JSON que devuelve el server
	//y podría, por ejemplo contener otros atributos como:
	//response.status, response.message,...
	return response.models;
    }
});

reset

Este método sirve tanto para limpiar el contenido de la collección, como para reemplazar el contenido por los nuevos modelos especificados por parámetro.

Además de estos métodos, existen muchos más métodos para trabajar con las colecciones, como: push, pop, shift, unshift, sort, pluck, where… Échale un vistazo a la documentación oficial para conocerlos a fondo.

Backbone.View

Las vistas en Backbone tienen la misión de organizar las distintas partes de la interfaz de la aplicación y mantenerlas actualizadas con el modelo. Backbone no hace suposiciones sobre nuestro HTML / CSS ni sobre el sistema de templates que queremos usar, por eso, las vistas en Backbone tienen más que ver con organización que con código. El siguiente ejemplo muestra la típica estructura de una vista:

var TaskView = Backbone.View.extend({
    tagName: "li",
    className: "task",

    initialize: function(){
        this.model.on('change', this.render, this);
    },
	
    render: function(){
        this.$el.html(_.template($('#taskTemplate').html(),this.model.toJSON()));
	return this;
    },
	
    events: {
        'click .delete': 'deleteAction'
    },
	
    deleteAction: function(){
        this.model.destroy();
        return false;
    }
});
var taskView = new TaskView({model: mytask, id: 'task-'+mytask.id});

constructor

El constructor para la vista acepta como en el caso de los modelos y las colecciones, un conjunto de atributos que se fijarán en el objeto. Lo común es especificar el modelo con los datos que van a ser representados y un id único que será usado como atributo en el DOM.

tagName y className

Son los atributos que nos permiten decirle a Backbone cual será el elemento raíz que contendrá la vista, en el caso anterior, se traducirá en: <li class=”task”></li>

el y $el

Son los atributos que almacenan la referencia a la raíz HTML de la vista. Siguiendo con el ejemplo, el sería un objeto DOM que representa <li class="task"></li>. $el es el objeto el encapsulado por jQuery para poder trabajar de forma más cómoda.

initialize

Es el método llamado en el momento de la creación del objeto, en el ejemplo, añadimos un listener para el evento change del modelo vinculado, de forma que cuando cambie un atributo del modelo, se vuelva a renderizar la vista, sin tener que preocuparnos de nada más.

render

Esta función se necesita sobreescribir para especificar como se va a mostrar la vista en la interfaz. Tienes total libertad de hacerlo como quieras, por ejemplo, puedes concatenar todo el contenido HTML en una string para luego añadirlo, o usar document.createElement o cualquier framework que gustes. Lo más aconsejable, es usar un sistema de templating como Mustache.js, Haml-js, Eco o jQuery Templates.

En el ejemplo anterior he usado Underscore.js y para que funcione, necesitas tener una template con el id taskTemplate en tu HTML. Tal que así:


events

Definiendo este atributo podemos especificar los distintos eventos del usuario sobre el DOM que representa la vista. La forma de definir un evento es "evento selector": "callback". Es importante tener en cuenta que el selector solo buscará en los nodos pertenecientes a this.el. En caso de omitir el selector, el evento se aplicará a this.el.

En el ejemplo, definimos el evento de cuando el usuario hace click en el link de Borrar, cuya clase CSS es delete, y le asignamos el callback deleteAction, la cual definimos en la siguiente línea.

Hasta aquí...

Hasta aquí la introducción a Backbone.js, creo que más o menos he listado las cosas más importantes, ¡pero hay más! Échale un vistazo a la documentación original.

¿Qué os ha parecido? ¿Creeis que Backbone.js va a ser un MUST como ya prácticamente lo es ahora jQuery, o conocéis otras librerías que le puedan arrebatar ese privilegio?

Este es el primero de una serie de tutoriales orientados a Backbone.js y desarrollo de aplicaciones en Javascript, así que estate atento, ¡proximamente más y mejor!

¿Necesitas desarrollar un proyecto web o para móviles? ¡Estamos disponibles!

Visitar Cokidoo

Cokidoo, los creadores de Ontuts, desarrollamos proyectos tecnológicos centrados en redes sociales y aplicaciones web, aplicaciones móviles y consultoría web y bases de datos.

Somos jóvenes, inquietos, versátiles, apasionados por la innovación y enfocados en las nuevas tecnologías. Con Ontuts tratamos de compartir nuestro conocimiento adquirido en los distintos proyectos, ayudando a la comunidad y mostrando nuestra capacidad tecnológica.

Si necesitas un presupuesto sin compromiso, estamos disponibles, no dudes en contactar con nosotros.

Comentarios en esta publicación (7 comentarios)

¿Te ha gustado esta publicación? ¡Puedes compartir tu opinión con todos nosotros! Simplemente pincha aquí mismo.

Me parece interesante y sin mucha configuración. Claro ahi vemos que esta Zend Framework o Wicket para manejar MVC pero que requieren mas configuraciones para que trabaje.

Backbone.js me parece una buena opcion para empezar a trabajar con MVC, gracias por el post, saludos

Álvaro Carneiro

Muy bueno, aunque no me he metido con Backbone he visto que muchos lo están empezando a usar y parece que es bastante funcional.
Veré si algún día me meto a ver que tal.

Por ahora me quedo con PHP y pjax

Muy buen aporte. Los diseñadores web poseen gran cantidad de opciones de trabajo teniendo en cuenta que hoy en día toda empresa necesita de manera imprescindible de un sitio en Internet donde publicitar sus productos y servicios.

Esto refiere a usar MVC del lado del cliente?

Genial!
En especial eso de poder conectar con el servidor a través de Json de una manera ya prevista y bien planificada… (yo lo había intentado casi con arco y flecha XD)

David

Backbone parece estar de moda, tambien can.js cual es mejor? Qud tiene uno que no tenga el otro.