Riot.js

Riot.js review
Cover image

(A repost from my 2016 article on medium )

I’m continually on the hunt for libraries and frameworks that make development either faster, easier, more fun, or bug-free. I have previously used a lot of Backbone, Angular 1, and React.

When I jumped onto a mostly static project that needed some interactive widgets I felt like neither Angular or React quite fit the bill. Angular 1 is great but it really wants to control the application and DOM. React is great too, but the amount of setup and decisions to make prior to writing any code is too much for this use case.

I thought I’d have a gander at micro frameworks and view libraries, rather than rely on the battle tested albeit messy jQuery. I looked at Vue, “Reactive Components for Modern Web Interfaces”. There are a few recommendations for it in the community also. I looked quickly at Preact, but it looks to be a slimmed version (ES6 focused) of React with a smaller community.

I ended up on Riot.js, I had only heard a few whispers of riot in the furthest reaches of twitter. The API for Riot.js is a developer dream, well for me. It is what was promised by polymer combined with React. It also casually solves scoped css with great elegance.

Here’s a Riot tag sample straight off the homepage:

<todo>

  <!-- layout -->
  <h3>{ opts.title }</h3>

  <ul>
    <li each={ item, i in items }>{ item }</li>
  </ul>

  <form onsubmit={ add }>
    <input>
    <button>Add #{ items.length + 1 }</button>
  </form>

  <!-- style -->
  <style scoped>
    h3 {
      font-size: 14px;
    }
  </style>

  <!-- logic -->
  <script>
    this.items = []

    add(e) {
      var input = e.target[0]
      this.items.push(input.value)
      input.value = ''
    }
  </script>

</todo>

Right off the bat, you see a bit of the React or JSX style of html in what will become javascript functions. They’ve even smoothed it over a bit, you don’t need to use className instead of class on the html. It doesn’t sound like a big difference but it is. Now anyone who knows html and css can jump on this file and goto town, leaving special attributes and curly braces alone.

Ok after seeing this really nice web component like API how do you get started? You add the tag to your html, anywhere you want <todo></todo> add the riotjs+compiler script weighing in 20kb, less than most spacer pixels. Then mount your tag and or tags.

Like so:

<html>
  <head>
    <title>Hello Riot.</title>
  </head>
  <body>
    <!-- place the custom tag anywhere inside the body -->
    <sample></sample>
    <!-- include the tag -->
    <script type="riot/tag" src="sample.tag"></script>
    <!-- include riot.js -->
    <script src="https://cdn.jsdelivr.net/riot/2.4/riot+compiler.min.js"></script>
    <!-- mount the tag -->
    <script>riot.mount('sample')</script>
  </body>
</html>

Now I really like Gulp, and I’m not against Webpack, but when I want to code I really, really like that I can add the riot+compiler library and get very fast performance, and just code. I like that I can code a component, and easily use it in another project. I like that with no work I have scoped css, custom html tags, and modularized code. Have a play with Riot here

Now then like React, Riot has a few simple lifecycle events to hook into. I’ve been using before-mount, mount, and unmount mostly. Here is the full list though. If you are coming from a jQuery world mount might feel like onReady. Which is loosely the same onReady = DOM (Document Object Model) has done rendering, and this.on(‘mount’, function(){}) is the Riot Element is mounted to the DOM. Here is where you can manipulate the DOM, and gain access to other elements etc. before-mount is where you might manipulate or gather some data that would effect what the element might render like in the mount phase. You could grab a made up API like ‘/animals’ then pass animals.types to mount and mount might say if ‘cats’ do this, if ‘dogs’ do that.

Transclusion, the biggest baddest, word in programming? If you want to ace an Angular interview pay close attention (I asked this all the time to candidates) What is transclusion? It’s really just like a window frame around something else. BOOM you got the job!

Most of the time when you work with a DOM node like a <div id=”app” /> you take all your rendered application and replace that node, or replace innerHTML. Transclusion is saying “Hey if somethings inside that div let’s keep it somewhere” So with Angular 1 you would do something like use an ngTransclude element to show where we are moving the innerHTML to. EJS a popular Node/Browser templating language use <%- yield %> and similarly <yield/> in Riot.js

There were a few things that I kinda figured out as I went along. They might be in the docs but I might have skimmed. One great thing is any element with either an id or name attribute is easily selected in the .tag file on the ‘this’ object.

<app>  
<form id=”important-form”></form>  <script>
   this.on(‘mount’, function(){ 
     console.info(this[‘important-form’]);
   });
 </script>
</app>

The other thing that wasn’t immediately clear was custom events and observables. The documentation makes them look super easy and powerful… and they are. It uses el but how do you get el, can one riot element lookup another by id and trigger and event? Can you use jQuery find the custom el and send back the unwrapped element $(“sample”)[0], or does Riot have a selector engine? I’m not 100% on all these but what does work, is creating a top level javascript object or class like in the documentation. Or what has worked for me so far:

this.parent.tags.calendar.trigger(‘customEvent’, 
  function() { return 1;}
)

So if the element is nested at all you can get access to sibling tags from this.parent which returns a POJO of custom elements, like my calendar. The second parameter is the data to send along, which can b e a string, number, object, or function… probably anything. So you could start to get fancy and put listeners on all the children for (tag in this.tags) {} but someone has tidied this up this with RiotControl a flux inspired library.

Feel free to make suggestions, corrections, comments below!

I’m @cactusanddove on twitter