Tiny (2 KB) turboboosted JavaScript library for creating user interfaces

Develop web apps with 100 % JavaScript and web standards.

Documentation

GitHub

RE:DOM is a tiny (2 KB) DOM library by Juha Lindstedt and contributors, which adds useful helpers to create DOM elements and keeping them in sync with the data.

Because RE:DOM is so close to the metal and doesn't use virtual dom, it's actually faster and uses less memory than almost all virtual dom based libraries, including React (benchmark).

It's also easy to create reusable components with RE:DOM.

Another benefit is, that you can use just pure JavaScript, so no complicated templating languages to learn and hassle with. Plus RE:DOM plays nicely with others. No need to write wrappers for things like Google Maps.

Learn more

Create HTML elements easily

import { el, mount } from 'redom';

// create HTML element
const hello = el('h1', 'Hello world!');

// mount to DOM
mount(document.body, hello);
<body>
  <h1>Hello world!</h1>
</body>

Add attributes

import { el, mount } from 'redom';

// create HTML element
const logo = el('img#redom-logo.logo', {
  src: 'img/logo.svg'
});

// mount to DOM
mount(document.body, logo);
<body>
  <img id="redom-logo" class="logo" src="img/logo.svg">
</body>

Listen to events

import { el } from 'redom';

// define Login component
export class Login {
  constructor () {
    this.el = el('form#login',
      this.email = el('input.email', { type: 'email' }),
      this.pass = el('input.pass', { type: 'password' }),
      this.submit = el('button', { type: 'submit' },
        'Sign in'
      )
    );
    this.el.onsubmit = e => {
      e.preventDefault();

      const email = this.email.value;
      const pass = this.pass.value;

      console.log(email, pass);
    };
  }
}
import { mount } from 'redom';
import { Login } from './login.js';

// create login
const login = new Login();

// mount to DOM
mount(document.body, login);
<body>
  <form id="login">
    <input class="email" type="email">
    <input class="pass" type="password">
    <button type="submit">Sign in</button>
  </form>
</body>

Sync lists

import { el } from 'redom';

// define <li> component
export class Li {
  constructor () {
    this.el = el('li');
  }
  update (i) {
    this.el.textContent = `Item ${i}`;
  }
}
import { list, mount } from 'redom';
import { Li } from './li.js';

// create list
const ul = list('ul', Li);

// update with data
ul.update([1, 2, 3]);

// mount to DOM
mount(document.body, ul);

// schedule another update
setTimeout(() => {
  ul.update([2, 3, 4, 5]);
}, 1000);
<body>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</body>

Sync tables

import { el, list } from 'redom';

// define <td> component
class Td {
  constructor () {
    this.el = el('td');
  }
  update (i) {
    this.el.textContent = i;
  }
}

// define <tr> component by extending list
export const Tr = list.extend('tr', Td);
import { list, mount } from 'redom';
import { Tr } from './tr';

// create table
const table = list('table', Tr);

// update with data
table.update([
  [ 1, 2, 3 ],
  [ 4, 5, 6 ],
  [ 7, 8, 9 ]
]);

// mount to DOM
mount(document.body, table);

// schedule another update
setTimeout(() => {
  table.update([
    [ 3, 2, 1 ],
    [ 6, 5, 4 ],
    [ 9, 8, 7 ]
  ]);
}, 1000);
<body>
  <table>
    <tr>
      <td>1</td><td>2</td><td>3</td>
    </tr>
    <tr>
      <td>4</td><td>5</td><td>6</td>
    </tr>
    <tr>
      <td>7</td><td>8</td><td>9</td>
    </tr>
  </table>
</body>

Create and update components

import { el, text } from 'redom';

// define component
export class Hello {
  // ..how to create it
  constructor () {
    this.el = el('h1',
      'Hello ',
      this.target = text('world'),
      '!'
    );
  }
  // ..and how to update it
  update (target) {
    this.target.textContent = target;
  }
}
import { mount } from 'redom';
import { Hello } from './hello.js';

const hello = new Hello();

hello.update('RE:DOM');

mount(document.body, hello);
<body>
  <h1>Hello RE:DOM!</h1>
</body>

Combine list + component

import { el, text } from 'redom';

// define component
export class Hello {
  // ..how to create it
  constructor () {
    this.el = el('h1',
      'Hello ',
      this.target = text(''),
      '!'
    );
  }
  // ..and how to update it
  update ({ id, target }) {
    this.target.textContent = target;
  }
}
import { list, mount } from 'redom';
import { Hello } from './hello.js';

// create list of Hello's
const hellos = list('section', Hello, 'id');

// init with some data
const data = [{
  id: 1,
  target: 'RE:DOM'
}, {
  id: 2,
  target: 'world'
}];

hellos.update(data);

// mount to DOM
mount(document.body, hellos);

// schedule an update
setTimeout(() => {
  const data = [{
    id: 2,
    target: 'world'
  }, {
    id: 1,
    target: 'RE:DOM'
  }];

  // reuses DOM elements and only reorders in this case!
  hellos.update (data);
}, 1000);
<body>
  <section>
    <h1>Hello RE:DOM!</h1>
    <h1>Hello world!</h1>
  </section>
</body>

Switch sections

const { el } = require('redom');

// define A component
export class A {
  constructor () {
    this.el = el('.a')
  }
  update ({ val }) {
    this.el.textContent = val;
  }
}
const { el } = require('redom');

// define B component
export class B {
  constructor () {
    this.el = el('.b')
  }
  update ({ val }) {
    this.el.textContent = val;
  }
}
const { el, router } = require('redom');
import { A } from './a.js';
import { B } from './b.js';

const routes = {
  a: A,
  b: B
};

// define main app component
export class App {
  constructor () {
    this.el = el('.app',
      this.sections = router('.content', routes)
    );
  }
  update ({ section, data }) {
    this.sections.update(section, data[section]);
  }
}
const { mount } = require('redom');
import { App } from './app.js';

// create app
const app = new App();

// init app
app.update({
  section: 'a',
  data: {
    a: 1,
    b: 2
  }
});

// mount to DOM
mount(document.body, app);

// update app after 1 second
setTimeout(() => {
  app.update({
    section: 'b',
    data: {
      a: 1,
      b: 2
    }
  });
}, 1000);
<body>
  <div class="app">
    <div class="content">
      <div class="a">1</div>
    </div>
  </div>
</body>

Works on server-side as well!

const { Document, render } = require('nodom');

// create a fake DOM before requiring RE:DOM
const document = new Document();

const { el, mount } = require('redom');

mount(document.body, el('h1', 'Hello world!'));

const html = render(document.body);

console.log(html); // <body><h1>Hello world!</h1></body>

Looks fun!

Documentation

GitHub