Introduction:
Reactivity is a key feature in modern web development, allowing for dynamic updates to the user interface based on changes in data or state. While frameworks like React, Vue, and Angular provide powerful tools for building reactive applications, it's also possible to implement reactivity with vanilla JavaScript. In this article, we'll explore how to build reactive HTML pages using only JavaScript, starting from scratch.
Step 1: Creating Reactive Values
To begin, we need a way to create reactive values in our application. These values will be the foundation of our reactive system, allowing us to track changes and update the UI accordingly. Here's a simple implementation of a reactive value:
function reactiveValue(initialValue) {
let value = initialValue;
const subscribers = [];
function get() {
return value;
}
function set(newValue) {
if (value !== newValue) {
value = newValue;
subscribers.forEach((subscriber) => subscriber());
}
}
function subscribe(subscriber) {
subscribers.push(subscriber);
}
return { get, set, subscribe };
}
This reactiveValue
function takes an initial value and returns an object with three methods: get
, set
, and subscribe
. The get
method simply returns the current value, while the set
method updates the value and notifies any subscribed functions. The subscribe
method allows us to register a function that will be called whenever the value changes.
Step 2: Creating Reactive Attributes
Next, we need a way to attach these reactive values to HTML elements. One approach is to create a custom attribute that we can add to any element. Here's an example of how we might define a data-reactive
attribute:
<div data-reactive="name"></div>
We can then use JavaScript to retrieve the value of this attribute and create a reactive binding between the element and the corresponding reactive value. Here's an example of how we might implement this:
const reactiveElements = document.querySelectorAll('[data-reactive]');
reactiveElements.forEach((element) => {
const name = element.dataset.reactive;
const value = reactiveValue(null);
// Set up a subscription to update the element when the value changes
value.subscribe(() => {
element.textContent = value.get();
});
// Update the value when the element changes
element.addEventListener('input', (event) => {
value.set(event.target.value);
});
});
In this example, we first select all elements with a data-reactive
attribute using document.querySelectorAll
. We then iterate over these elements and extract the name of the reactive value from the attribute. We create a new reactive value with the initial value of null
, and set up a subscription to update the element whenever the value changes. Finally, we add an event listener to update the value whenever the element changes.
Step 3: Creating Reactive Expressions
While reactive attributes allow us to bind individual elements to reactive values, we often want to perform more complex operations involving multiple values. To handle this, we can create reactive expressions, which are functions that take one or more reactive values as inputs and produce a new reactive value as output. Here's an example of how we might implement a simple reactive expression:
function reactiveExpression(fn, ...values) {
const result = fn(...values.map((value) => value.get()));
const dependencies = values.filter((value) => value instanceof ReactiveValue);
const reactiveValue = reactiveValue(result);
dependencies.forEach((dependency) => {
dependency.subscribe(() => {
reactiveValue.set(fn(...dependencies.map((value) => value.get())));
});
});
return reactiveValue;
}
This reactiveExpression
function takes a function fn
and one or more reactive values as arguments. It calls fn
with the current values of the input reactive values, and creates a new reactive value with the result. It then sets up subscriptions to update the output reactive value whenever any of the input reactive values change.
Here's an example of how we might use reactiveExpression
to create a reactive expression that calculates the sum of two reactive values:
const a = reactiveValue(1);
const b = reactiveValue(2);
const c = reactiveExpression((x, y) => x + y, a, b);
In this example, we create two reactive values a
and b
with initial values of 1 and 2, respectively. We then create a reactive expression c
that adds a
and b
together, using the reactiveExpression
function. Whenever either a
or b
changes, the c
reactive value will be updated automatically.
Conclusion:
Building reactive HTML pages with vanilla JavaScript involves creating reactive values, attaching them to HTML elements, and combining them using reactive expressions. By following these steps, we can create robust and scalable reactive systems without the need for large frameworks. Whether you're building a simple form
Top comments (2)
Nice, thank you
I love the approach, we use vanilla JS sometimes, such approaches are great insight!