LiteralJS
~1kb JavaScript library for building user interfaces.
$ microbundle
Build output to build:
1.13 kB: index.js
1.14 kB: index.m.js
1.19 kB: index.umd.js
Features and stuff
- Small: Only around 1kb in size.
- Virtual DOM: Diffing occurs on state update for more efficient DOM updates. Current and previous AST are diffed against each other.
- Lifecycle Methods: All DOM elements have the ability to trigger
mounted
and unmounted
lifecycle functions using built-in JavaScript MutationObservers
. - One Global Store: One source of truth; State management libraries are less of a need.
API Function Index
Getting Started
Install
$ npm install literaljs
$ yarn add literaljs
Import
const Literal = require('literaljs');
import Literal from 'literaljs';
import { component, render } from 'literaljs';
ES6 Example
import { component, render } from 'literaljs';
const foo = component({
render: ({ getState, setState }) => ({
element: 'div',
class: 'container',
text: `This is the Count: ${getState().count}`,
children: [
{
element: 'button',
text: 'Click Me!',
events: {
type: 'click',
action: () => {
var state = getState();
setState({ count: state.count + 1 });
}
}
}
]
})
});
render(foo, 'app', { count: 0 });
At the moment, all components are created with just objects. There is also more succinct markup and use for those who have access to ES6+ features like object destructuring.
In the near future regular html markup will be also possible as well!
component
The component
function accepts objects with the following keys:
component props
The props
of a component
is an object which can be passed with anything that is normally valid in a JavaScript Object. This can include any data or functions.
The only component that can not recieve props
is the root component that is passed to the Literal.render
function.
Example:
const bar = component({
render: ({ getState, setState, props }) => ({
element: 'p',
text: `Total: ${props.total}`
})
});
const foo = component({
render: ({ getState, setState }) => ({
element: 'div',
children: [
bar({ props: { total: 9 } })
]
})
});
component methods
The methods
key of a component
will accept a function which returns an object of other functions. Within the methods
, you also have access to a component
s getState
and setState
functions which can be used accordingly. You also, have access to created methods directly within the render
function.
Example:
component({
methods: ({ getState, setState }) => ({
increase: () => {
const count = getState().count;
setState({ count: count + 1 });
}
}),
render: ({ getState, setState, methods: { increase }}) => ({
element: 'button',
text: `Current Count: ${getState().count}`,
events: {
type: 'click',
action: () => increase()
}
})
});
component render
The render
key of a component
accepts a function that returns an JavaScript Object.
Markup Syntax
Markup is currently written with Objects with the following specified keys:
* = Required Key
element Key
The element
key in the render
function markup is the HTML node tag name as a String
. For example, an element
with the value
The element
key is required when generating a new DOM node.
Example:
component({
render: () => ({
element: 'div',
})
});
text Key
The text
key in the render
function markup accepts a String an will generate a text inside the element.
Example:
component({
render: () => ({
element: 'div',
text: 'Hello World!'
})
});
class Key
The class
key in the render
function markup is the HTML node class name as a String
.
Example:
component({
render: () => ({
element: 'div',
class: 'title'
})
});
id Key
The id
key in the render
function markup is the HTML node class name as a String
.
Example:
component({
render: () => ({
element: 'div',
id: '2'
})
});
Children Key
The children
key in the render
function markup is the childNodes
of a given element
or DOM Node. This key only accepts an Array of Objects. Each Object in this Array can be another Object that represents a new DOM Node.
Example:
component({
render: () => ({
element: 'div',
children: [
{
element: 'span'
}
]
})
});
Events Key
The events
key in the render
function markup accepts either an Array of events or a single event Object.
An event object has two keys:
type
(Event Name)action
(Function To Trigger)
Example:
component({
render: () => ({
element: 'button',
text: 'Click Me!',
events: [
{
type: 'click'
action: () => console.log('Hello World!')
}
]
})
});
component({
render: () => ({
element: 'button',
text: 'Click Me!',
events: {
type: 'click'
action: () => console.log('Hello World!')
}
})
});
Lifecycle Events
Besides the common event handlers like click
, there are two lifecycle events that LiteralJS
includes that can be attached to any DOM node.
To do so, just name the type
value unmounted or
mounted` to trigger functions when a DOM node is first placed in the DOM or removed from the DOM.
Example:
Example:
component({
render: () => ({
element: 'div',
text: 'I have a life!',
events: [
{
type: 'mounted'
action: () => console.log('I\'m on the page!')
},
{
type: 'unmounted'
action: () => console.log('I\'m off the page!')
}
]
})
});
Other Keys Not Listed
Other keys are also accepted in a DOM object, such as data
and other custom keys.
Properties
Within the render
function of a component, you have access to other functions and objects:
getState
The getState
function of the component
s render
method will allow you to access the global store of your application.
setState
The setState
function of the component
s render
method accepts an object which will allow you to set new values for particular pieces of state in the global store
props
The props
object of the component
s render method can contain any number of data types and functions. The only
componentthat cannot contain
propsis the root
componentthat is passed to the
Literal.render` method.
methods
The methods
object allow you to access other functions defined directly in the component
. You can use this as a way to organize other pieces of logic and keep the render
function much cleaner.
render
The Literal.render
function is responsible for parsing the AST that is provided with component
s, injecting the generated markup into the specific DOM node, diffing any new changes based on state, and setting the default application state.
The Literal.render
function can accept 3 arguments, one of which is optional.
- The root component.
- The String
id
of the DOM node to inject generated markup with. - (Optional) The default state as an Object
Example:
Literal.render(component, 'app', { count: 0 });
render(component, 'app');