Welcome to the documentation for a.js, a lightweight JavaScript flexwork designed to empower developers with flexibility and transparency. This guide will walk you through the core concepts, features, and best practices of a.js.
a.js is easy to integrate into your projects. Follow these steps to get started:
Include the a.js script in your HTML file:
<script src="path/to/a.js"></script>
Replace path/to/a.js
with the actual path to the a.js file in your project.
Create a basic a.js script using the <a-closure>
tag. For example:
<div>
<a-closure>
<let>
global watched g.message
</let>
g.message = "Hello, a.js!";
{(<strong>${g.message}</strong>)}
</a-closure>
</div>
This script declares a reactive variable g.message
and renders it dynamically in the DOM.
<a-tagDef>
and <a-closure>
to define and manage components.watched
variables.Start by experimenting with the examples in this guide, and refer to the sections below for deeper insights into specific features and functionalities.
In this section, we explore the core concepts of a.js, starting with the building blocks that make it powerful and flexible.
At the heart of a.js is the ability to create and manage custom HTML elements with ease. The <a-tagDef>
tag allows you to define reusable components with minimal effort. Here's a simple example:
<a-tagDef fortag="my-button">
{(<button>Click Me!</button>)}
</a-tagDef>
<my-button></my-button>
In this example, <my-button>
becomes a custom tag that renders a button element. You can use this tag anywhere in your HTML.
To make your custom elements dynamic, a.js leverages JavaScript template literals, which allow you to embed dynamic content. For example:
<a-tagDef fortag="interactive-message">
<let>
global watched g.text
</let>
g.text = "Hello, Dynamic World!";
function updateMessage() {
g.text = "Message Updated!";
}
{(<div>
<p>${g.text}</p>
<button onclick="updateMessage()">Update Message</button>
</div>)}
</a-tagDef>
<interactive-message></interactive-message>
This example demonstrates how to:
watched
variable, g.text
, to make it reactive.updateMessage
function.g.text
in the DOM, showcasing reactivity.When you click the button, the text in the paragraph will change instantly without the need for manually updating the DOM. This is the power of reactivity in a.js.
<a:tag>
to avoid potential conflicts with native HTML tags when using template literals.
Reactivity is a core feature of a.js, enabling automatic updates to the DOM when variables change. This is achieved through the use of watched
variables. In this section, we delve deeper into how reactivity works.
Watched variables are special variables that a.js observes for changes. When their values are updated, any part of the DOM that depends on them is automatically refreshed. This eliminates the need for manual DOM manipulation.
Watched variables are declared using the watched
keyword inside a <let>
block. For example:
<a-closure>
<let>
global watched g.counter
</let>
g.counter = 0;
</a-closure>
This code initializes a watched
variable, g.counter
, with a value of 0
.
You can bind watched variables to the DOM using template literals. Here's an example:
<a-closure>
<let>
global watched g.counter
</let>
g.counter = 0;
function incrementCounter() {
g.counter++;
}
{(<div>
<p>Counter: ${g.counter}</p>
<button onclick="incrementCounter()">Increment</button>
</div>)}
</a-closure>
In this example:
g.counter
is displayed in a paragraph tag.incrementCounter
function to update g.counter
.g.counter
changes.When you click the button, the counter value increases and the DOM updates seamlessly.
Watched variables can be scoped globally, to namespaces, or to a parent-child relationship. The scope is defined by the namespace
attribute of the <a-closure>
tag. For example:
<a-closure namespace="myNamespace">
<let>
nsGlobal watched g.counter
</let>
g.counter = 10;
</a-closure>
This code declares a watched
variable g.counter
within the namespace myNamespace
.
<let>
DeclarationsThe <let>
block supports several keywords for declaring variables with specific scopes:
local
: Declares variables in the local context.global
: Declares variables in the global context.nsGlobal
: Declares variables in the current namespace defined by the namespace
attribute of the <a-closure>
tag.dGlobal
: Declares variables in a parent <a-closure>
's scope.aGlobal
: Accesses variables declared with dGlobal
from descendant closures.watched
: Makes variables reactive, updating the DOM automatically when their values change. Combine this with the previous keywords, like local watched local.var
Managing application state effectively is critical in dynamic applications. a.js provides powerful tools to save, restore, and manipulate application states with minimal effort.
With a.js, you can save the current state of your application using A.dumpAllStates()
. This function captures all reactive states in the application.
// Save the current state
let savedState = A.dumpAllStates();
This returns a serialized string representing the current state of all watched variables and reactive contexts.
To restore a previously saved state, use A.restoreAllStates(stateDump)
. This function takes a serialized state string as input and updates all watched variables to match the saved state.
// Restore a previously saved state
A.restoreAllStates(savedState);
Once the state is restored, the DOM automatically updates to reflect the restored values, demonstrating the seamless integration of reactivity and state management.
Here’s an improved example demonstrating state saving and restoration while ensuring that the application always has a meaningful state to revert to:
<a-closure>
<let>
global watched g.text
</let>
g.text = "Initial State";
let stateHistory = [A.dumpAllStates()];
function saveState() {
stateHistory.push(A.dumpAllStates());
}
function restoreState() {
if (stateHistory.length > 1) {
stateHistory.pop();
A.restoreAllStates(stateHistory[stateHistory.length - 1]);
}
}
function updateText() {
g.text = `Updated at ${new Date().toLocaleTimeString()}`;
saveState();
}
{(<div>
<p>${g.text}</p>
<button onclick="restoreState()">Undo</button>
<button onclick="updateText()">Update Text</button>
</div>)}
</a-closure>
In this example:
stateHistory
array to store successive states.Update Text
button updates g.text
and automatically saves the new state.Undo
button restores the previous state by removing the latest entry from stateHistory
.With this approach, the application always has a meaningful state to revert to, ensuring a smooth user experience.
The advanced features of a.js empower developers with dynamic tools for building flexible, high-performance applications. These features include scoped contexts, redefinable custom elements, and dynamic templates, allowing fine-grained control and customization.
Scoped contexts help organize and manage application state, preventing naming collisions and ensuring variables are accessible only where needed. The namespace
attribute of the <a-closure>
tag defines the active namespace for variables declared within it.
<a-closure namespace="exampleNamespace">
<let>
nsGlobal watched g.message
</let>
g.message = "Scoped to exampleNamespace";
{(<p>${g.message}</p>)}
</a-closure>
Here, g.message
belongs to the exampleNamespace
, ensuring it does not conflict with similarly named variables in other contexts.
With a.js, you can redefine the behavior of custom elements dynamically. This feature is useful for updating components at runtime without needing a full reload.
<a-tagDef fortag="dynamic-element">
{(<div>Original Element</div>)}
</a-tagDef>
<dynamic-element></dynamic-element>
<script>
// Initially defined behavior
setTimeout(() => {
// Redefine the behavior dynamically
A.tagDef({
fortag: "dynamic-element",
content: `{(<div>Redefined Element</div>)}`
});
A.replayCustomTagsByName("dynamic-element");
}, 3000); // Wait 3 seconds before redefinition
</script>
Initially, <dynamic-element>
displays "Original Element." After 3 seconds, the component dynamically updates to "Redefined Element," showcasing runtime redefinition.
Dynamic templates in a.js allow you to build responsive UIs that update seamlessly with changes to state or variables. Using template literals with reactive variables ensures efficient DOM updates.
<ul>
<a-closure>
<let>
local watched g
</let>
g.arr = [1,2,3,4,5]
let count = 6;
{(<button onclick="g.arr.push(count++)">push</button>)}
{(<button onclick="g.arr[1]--">--</button>)}
{(<button onclick="g.arr.pop()">pop</button>)}
{(<button onclick="g.arr.shift()">shift</button>)}
<forEachOf g.arr="val">
{(<li key="${forEach}">(${val}-${g.arr[forEach]})</li>)}
</forEachOf>
</a-closure>
</ul>
In this example:
forEachOf
loop dynamically creates and appends <li>
elements to a <ul>
element as items are added to g.arr
.