0.0.5 • Published 3 years ago
domez v0.0.5
DOMEZ
A tiny lib for DOM rendering
Installation
with NPM
npm i domez --save
with YARN
yarn add domez
Features
- No boilerplate
- No bundler
- Tiny size (5KB)
Motivation
There are many frameworks for DOM manipulation like React, Angular, Vue, etc. they are difficult to learn and cumbersome. Domez was born to process the DOM rendering with ease, instead of using Vanilla JS. Domez also makes debugging convenient and easy. It is also compatible with many CSS Frameworks like Tailwind JS, Bootstrap JS
Recipes
Hello World
With DOMEZ
import { render } from "domez";
// define App block builder, the builder returns HTML template that will be rendered into the container
const App = ({ ref }) => {
// handle button click event
const buttonRef = ref({ onclick: () => alert("Hello World. " + new Date()) });
return `<button ${buttonRef}>Greeting</button>`;
};
// use body as rendering container
render(document.body, App);
Compare to Vanilla JS
const App = () => {
document.body.innerHTML = `<button id="greeting">Greeting</button>`;
document.getElementById("greeting").onclick = () =>
alert("Hello World. " + new Date());
};
App();
As you see, if we use Vanilla JS, the app code looks verbose, hard to mainternant and extend. Let's see complex example
Simple Todo App
import { render } from "domez";
const Todo = ({ ref }, todo) => {
// a block builder can return a controller object
// the controller object must have template property, it uses to render the block
return {
// expose the todo object for external access
todo,
template: `<div ${ref({ onclick: todo.onRemove })}>${todo.id}: ${
todo.title
}</div>`,
};
};
const App = ({ list, ref }) => {
let uniqueId = 1;
const inputRef = ref();
// create a element list and specific builder for each item
const todoList = list(Todo);
const handleAdd = () => {
const id = uniqueId++;
// inputRef() returns current ref of target element
const title = inputRef().value;
// remove an list item that has id equals to current todo id
// the list item is block controller that returns from block builder function
const onRemove = () =>
todoList.remove((todoController) => todoController.todo.id === id);
// this param will be passed to Todo builder as second parameter
// after creating the child block, the list will store the block controller for later use
const param = { id, title, onRemove };
todoList.push(param);
inputRef().value = "";
inputRef().focus();
};
return `
<div>
<input ${inputRef} /><button ${ref({ onclick: handleAdd })}>Add</button>
${todoList}
</div>
`;
};
render(document.body, App);
Compare to Vanilla JS
const createTodo = (todo) => {
const div = document.createElement("div");
div.onclick = () => div.remove();
div.textContent = `${todo.id} ${todo.title}`;
return div;
};
const App = () => {
let uniqueId = 0;
document.body.innerHTML = `
<input id="input"/><button id="button">Add</button>
<div id="list"></div>
`;
const $input = document.getElementById("input");
const $button = document.getElementById("button");
const $list = document.getElementById("list");
$button.onclick = () => {
const id = uniqueId++;
const title = $input.value;
const $todo = createTodo({ id, title });
$list.appendChild($todo);
$input.value = "";
$input.focus();
};
};
App();
Using element ref
const App = ({ ref, effect }) => {
const divRef = ref();
// WRONG: the div ref is not ready here
divRef().textContent = "Hello World";
// RIGHT: use effect to make sure all refs are ready to use
effect(() => {
divRef().textContent = "Hello World";
});
return `<div ${divRef}></div>`;
};
Set initial props/style for specified element
const App = ({ ref }) => {
return `<div ${ref({
text: "Hello World", // OR you can set inner HTML { html: '<i>Hello World</i>' }
style: "color: red", // OR { style: { color: 'red' } }
onclick: () => alert("Hello World"),
// OR { class: 'my-class' }
class: {
btn: true,
"btn-primary": true,
},
})}></div>`;
};
// that equipments to this
const App = ({ ref, effect }) => {
const divRef = ref();
effect(() => {
divRef().textContent = "Hello World";
divRef().onclick = () => alert("Hello World");
divRef().classList.add("btn");
divRef().classList.add("btn-primary");
divRef().style.cssText = "color: red";
});
return `<div ${divRef}></div>`;
};
Caveats
Do not use self closing tag
Some frameworks accept self-closing tag for shorter code but this might lead to unexpected error if you use it with DOMEZ
WRONG
template = `<h1/>`;
RIGHT
template = `<h1></h1>`;
// it's ok
template = `<input/>`;