Slug: riotjs-tutorial-1 Author: alexander
Ahora que cuento con un tanto de tiempo libre, es momento de revisar algunos frameworks javascript.
Después de analizar las opciones (y vaya que son muchas) comenzaré con RiotJS1.
RiotJS es un framework javascript minimalista, entre sus características destacadan: el sistema de etiquetas personalidadas, su sencilla sintaxis y su pequeño tamaño.
Nota: Este tutorial es una adaptación de "The react tutorial for riot", el cual a su vez es otra adaptación del tutorial de ReactJS para RiotJS.
El objetivo del tutorial2 es construir un sistema de comentarios que podría incluirse en un blog. Las características de este sistema son:
- Tiene una vista de todos los comentarios anteriores
- Cuenta con un formulario para registrar nuevos comentarios
- Se integra con un backend para almacenar los comentarios3
Y como adicionales:
- Comentarios optimistas: los comentarios aparecen antes de ser registrados en el backend
- Actualizaciones en vivo, es posible ver los comentarios de otras personas en tiempo real.
1. Estructura
Los bloques a considerar para nuestra implementación son:
- CommentBox
- CommentList
- Comment
- CommentForm
Los cuales se refieren al contenedor general, la lista de comentarios, cada comentario propiamente dicho y al formulario.
Como mencionamos, uno de los puntos fuertes de Riot es que nos permite usar etiquetas personalizadas. Para aprovechar esto crearemos un archivo llamado comments.tag y escribiremos lo siguiente en el:
::text
<comment-box>
<h1>Comentarios</h1>
<comment-list comments={ comments } />
<comment-form />
</comment-box>
<comment-form>
<form>
<input type="text" name="name">
<textarea name="message"></textarea>
<input type="submit" value="Publicar">
</form>
</comment-form>
<comment-list>
<comment each={ opts.comments } />
</comment-list>
<comment>
<div>
<h2>Mi nombre</h2>
<p>Mi comentario</p>
</div>
</comment>
Lo anterior representa a los bloques inicialmente descritos:
- Nuestro
comment-box
que tiene un elementocomment-list
al cual le está pasando como parámetro la lista de comentarios. - El
comment-form
que representa al formulario por el que se registran nuevos comentarios - El
comment-list
que contiene una lista de elementoscomment
sobre la que va a iterar. - El
comment
que es el comentario propiamente dicho.
2. Montar los componentes
Ahora que tenemos los componentes, vamos a integrarlos con nuestra web.
Nuestro archivo HTML principal (index.html) debe lucir similar a:
::html
<html>
<head>
<title>Sistema de comentarios</title>
<script src="https://cdn.jsdelivr.net/g/riot@2.0.11"></script>
</head>
<body>
<comment-box></comment-box>
<script src='comments.js'></script>
<script>
riot.mount('comment-box');
</script>
</body>
</html>
En el html, hemos incluido nuestro contentenedor general (<comment-box>
), el archivo comments.js
y un script que monta4 nuestra etiqueta <comment-box>
.
Observen además que hemos incluido un script comments.js
en el documento, este se obtiene al compilar nuestro archivo comments.tag.
Para compilar el archivo .tag
tenemos dos opciones:
1. Incluir el archivo compiler.js
en el head de nuestra página
2. Compilar en el lado del servidor, para ello necesitamos instalar riot mediante npm:
npm install riot
Con ello tendremos acceso al binario riot, al cual le indicaremos que observe los cambios en los archivos tag en nuestro directorio actual y los compile:
riot -w .
Para comprobar si todo va bien hasta ahora, podríamos levantar un servidor en local:
python -m SimpleHTTPServer
si vamos a 127.0.0.1:8000
, veremos que solo se ha cargado el formulario (nota: verificar que no exista ningún error en el inspector de elementos5)
En el siguiente paso añadiremos algunas funcionalidades.
3. Incluyendo variables y estados
Otra de las características de riot nos permite enviar variables al tag6 que estamos montando.
Editamos el archivo index.html
, cambiamos la línea que monta el tag por:
riot.mount('comment-box', {title: 'Comentarios'});
y actualizamos nuestro archivo .tag
para que incluya nuestra variable title
:
::text
<comment-box>
<h1>{ opts.title }</h1>
<comment-list comments={ comments } />
<comment-form />
</comment-box>
*Las opciones que enviamos a nuestro tag como contexto quedan almacenadas en la variable opts
7, con lo que el título de nuestra tag será el parámetro que enviamos.
Añadiendo un poco más de código para manejar el registro de nuevos comentarios:
::text
<comment-box>
<h1>{ opts.title }</h1>
<comment-list comments={ comments } />
<comment-form />
this.comments = []
add(comment) {
this.comments.push(comment)
}
</comment-box>
<comment-form>
<form onsubmit={ add }>
<input type="text" name="name">
<textarea name="message"></textarea>
<input type="submit" value="Publicar">
</form>
add(e) {
var comment = {
name: this.name.value,
message: this.message.value
}
this.parent.add(comment)
e.target.reset()
}
</comment-form>
<comment-list>
<comment each={ opts.comments }/>
</comment-list>
<comment>
<div>
<h2>{ this.parent.name }</h2>
<p>{ this.parent.message }</p>
</div>
</comment>
Hemos creado una función add(e)
que maneja el evento onsubmit de nuestro formulario. Esta función captura los valores ingresados, los envía al tag padre (<comment-box>
) y resetea8 el formulario. Observe que los campos con un atributo name se pueden acceder directamente mediante this.name
En el tag <comment-box>
se tiene otra función que inserta el comentario en la lista de comentarios.
También, en nuestra etiqueta comment
estamos mostrando los atributos name
y message
de cada iteración, por medio de los atributos del padre.
Otra opción más "explícita" sería enviando el nombre y mensaje como variables de contexto:
::text
<comment-list>
<comment each={ opts.comments } name={ this.name } message={ this.message }/>
</comment-list>
<comment>
<div>
<h2>{ opts.name }</h2>
<p>{ opts.message }</p>
</div>
</comment>
Con lo realizado hasta ahora, podemos volver a abrir nuestro navegador y probar.
4. Carga y persistencia de nuestros comentarios
Lo que sigue es implementar la comunicación de nuestra aplicación con algún backend para que los comentarios registrados queden almacenados. Para el ejemplo, voy a utilizar Parse.
Nos registramos y creamos una nueva aplicación. Luego copiamos los valores del Application ID
y el Javascript Key
.
En nuestro archivo html debemos insertar el script de parse (para facilidad nuestra, podemos usar el del CDN):
<script src="//www.parsecdn.com/js/parse-1.3.4.min.js"></script>
Luego, debemos inicializar la aplicación:
Parse.initialize("APP_KEY", "JS_KEY");
En nuestra etiqueta comment-box
, modificamos el método add
para que también registre el comentario en Parse:
::javascript
add(comment) {
this.comments.push(comment)
var Comment = Parse.Object.extend("Comment")
var _comment = new Comment()
_comment.save(comment)
}
Añadimos también un método load
que realizará la carga de comentarios desde Parse:
::javascript
load() {
var self = this
var Comment = Parse.Object.extend('Comment')
var queryComment = new Parse.Query(Comment)
queryComment.find({
success: function (results) {
var tmp_comments = []
for (var i = 0; i < results.length; i++) {
tmp_comments.push(results[i].toJSON())
}
self.update({'comments': tmp_comments})
},
error: function (error) {
alert("Error: " + error.code + " " + error.message)
}
})
}
Nótese que al terminar de recuperar los comentarios, estamos activando manualmente el evento update para que se refresquen los comentarios visibles.
También debemos iniciar nuestro método manualmente al menos una vez this.load()
.
Luego, para que el sitio refresque los comentarios cada cierto tiempo, podemos añadir:
setInterval(this.load, opts.interval)
Y en nuestra llamada al mount
en el index, agregamos el parámetro interval:
riot.mount('comment-box', {title: 'Comments', interval: 2500});
Pueden revisar la versión final del código en este gist.
Como se observa en el resultado final, lo que me sorprende es la poca cantidad de código que se requiere para tener un sistema de comentarios con persistencia en el backend haciendo presente que tampoco se pierde legibilidad en el código.
Referencias:
-
El plan original incluye revisar AngularJS y ReactJS también. ↩
-
El detalle es casi idéntico al tutorial de ReactJS, tan solo difiere en la capacidad para realizar comentarios con markdown. ↩
-
RiotJS llama montar al proceso de incluir nuestras etiquetas personalizadas y su respectiva lógica en el documento HTML. ↩
-
Me refiero al inspector de elementos de chrome o a su equivalente en firefox. ↩
-
tag o etiqueta ↩
-
Se puede acceder al elemento que origina el evento con
e.target
. Para más detalle, consultar la documentación: https://muut.com/riotjs/guide/#event-object ↩
Comentarios !
comments powered by Disqus