A virtual DOM alternative to build declarative and reactive UI using template literal tags.
- Highly Flexible: Use expressive JavaScript templates that can render anything to HTML. Set properties and event listeners directly from the template.
- Extremely Performant: Using the latest generation of rendering techniques, it easily outperforms contemporary VirtualDOM-based rendering as used in modern frontend frameworks.
- Lightweight: ~2.6kb total size.
- Extensible: Create components, pass props, handle lifecycle events and efficiently update the DOM by using HTML templating.
amp-js
lets you write HTML templates in JavaScript with template literals.
import { html, render } from '@arish-shah/amp';
// This is an amp template function. It returns an amp template.
const helloTemplate = (name) => html` <div>Hello ${name}!</div> `;
// This renders <div>Hello Ben!</div> to the document body
render(helloTemplate('Ben'), document.body);
// This updates to <div>Hello Rey!</div>, but only updates the ${name} part
render(helloTemplate('Rey'), document.body);
The render
function will render any type of object into the content of an HTML Node
, usually the document body, a container element, or a shadowRoot.
The first argument is the object that will be rendered. It can be one of the following:
- A
TemplateResult
(returned by thehtml
tag) - A string, number, or boolean
- An HTML DOM Node
- An Array-like object
Any other object is coerced to a String before being rendered.
The second argument is the Node
that the object will be rendered into. The previous content of the Node
will be removed.
The html
is a JavaScript template tag that allows creation of flexible templates which will be interpreted as HTML. To use the tag, prepend it to any JavaScript template literal.
const template = () => html` <p>Hello World</p> `;
The contents of the template will be parsed as HTML. The flexibility comes from interpreted values that can be inserted into these templates.
const template = (name) => html` <p>Hello ${name}!</p> `;
These interpreted values can in turn be any kind of object that amp-js can render, including nested templates and arrays.
The component
function can be used to create custom reusable components. It is provided with the default export.
- Each component has a first argument
id
, which helps amp-js locate its usage. - The second parameter is a description object that contains an optional dynamic data object, methods to mutate them, props passed to the component, templates used inside it and the template itself. amp-js automatically binds
this
to the data, so they can be effectively changed causing a rerender. - Each component should have a template function which gets called upon component creation.
- Execution of this function returns another function that can be called repeatedly to efficiently update the content.
- Changing the data members inside a component causes it to update automatically.
const Hello = Amp.component('amp-hello', {
template() {
return html`<h1>Hello World</h1>`;
}
});
Hello.generate();
The component can be consumed in HTML as such:
<amp-hello></amp-hello>
For a more complex component,
import Amp, { html } from 'https://unpkg.com/@arish-shah/amp';
const Counter = Amp.component('amp-counter', {
data: {
count: 0,
step: 1
},
onmount() {
this.count = +this.attr('start');
this.step = +this.attr('step');
},
methods: {
decrement() {
this.count -= this.step;
},
increment() {
this.count += this.step;
}
},
template() {
return html`
<div class="counter">
<button @click=${this.decrement}>Decrement</button>
<span>${this.count}</span>
<button @click=${this.increment}>Increment</button>
</div>
`;
}
});
Counter.generate();
We can now create multiple app-counter
component in our HTML, passing start
and step
as props:
<!-- Starts counter with 5 and increments/decrements by 5 -->
<app-counter start="5" step="5"></app-counter>
<!-- Starts counter with 8 and increments/decrements by 3 -->
<app-counter start="8" step="3"></app-counter>
The html
tag can also be used to set attributes on nodes. To set an attribute, assign the value of the attribute with an interpreted value. amp-js requires that you omit the surrounding "
when setting attributes.
const template = (source) => html` <img src=${source} /> `;
// Composite attribute
const template = (classString) => html`
<div class=${`red ${classString}`}></div>
`;
You can set boolean attributes by prefixing the attribute name with ?
const template = (secret) => html` <p ?hidden=${secret}></p> `;
You can set properties on elements by prefixing an attribute name with .
const template = (user) => html` <user-panel .user=${user}></user-panel> `;
You can attach event handlers by prefixing an attribute name with @
const handleClick = () => {
alert('clicked the button');
};
const template = () => html` <button @click=${handleClick}></button> `;
amp-js is distributed on npm, in the @arish-shah/amp
package.
$ npm install @arish-shah/amp
You can also load amp-js directly from the unpkg.com CDN:
import Amp, { html, render } from 'https://unpkg.com/@arish-shah/amp';
Or, you can create an index.html
file and include amp-js with:
<!-- development version -->
<script type="module">
import Amp, {
html,
render
} from 'https://unpkg.com/@arish-shah/amp@latest/amp.js';
</script>
<!-- production version -->
<script type="module">
import Amp, {
html,
render
} from 'https://unpkg.com/@arish-shah/amp@latest/amp.min.js';
</script>