Last week, my friend Chris Ferdinandi wrote a fantastic post about creating a clock with vanilla JS. I want to show you how to do the same thing with Reef, the wonderful anti-framework he created and maintains. It's a simple alternative to modern JavaScript frameworks like React and Vue.
The HTML
Before we do anything, let's look at the markup I started with:
<h1>Clock</h1>
<div id="app">
<p>Please enable JavaScript to use this clock.</p>
</div>
The most important thing to note is that I added a "please enable JavaScript" message inside the #app
element. If JavaScript is enabled, we change the content of the #app
element so this message isn't seen. If not, the user sees a message informing them what to do.
The JavaScript
Immediately-invoked function expression (IIFE)
First things first, I created an immediately-invoked function expression (IIFE) to contain the rest of my code. This allows me to keep my code outside the global scope and avoid naming conflicts with other scripts. I also opted into strict mode to make my code less error-prone:
;(function () {
"use strict";
})();
Variables
Inside my IIFE, I created my component using Reef:
// Create the component
const app = new Reef("#app", {
data: {
time: new Date().toLocaleString()
},
template: function (props) {
return `<p>${props.time}</p>`;
}
});
The first argument I've passed into the Reef
contructor is the element I want to render the component into. I've used #app
as my selector.
The second argument is an object literal containing my options. Its data
property is the state/data for the component. I've added a time
property with the current date and time as a string. To get the date and time, I called the toLocaleString()
method on an instantiation of the Date()
constructor.
The template
property is a function which returns the markup for the component. The props
parameter represents the component's state/data stored in the data
property. I've returned a paragraph element containing the date/time string. I used a template literal, but if you need to support IE, go with old-school string concatenation.
Functions
Next up, I created a function to update the time
property of my data:
/**
* Update the time property in the data
*/
function updateTime () {
app.data.time = new Date().toLocaleString();
}
Reef will reactively update the UI for me whenever I call this function.
Inits & Event Listeners
Finally, I initialized my app:
// Initialize the app
app.render();
// Update the time every second
window.setInterval(updateTime, 1000);
I called Reef's render()
method to run an initial render, and used my updateTime()
function as the callback for the setInterval()
method. I set it to run every second (every 1000 milliseconds).
Wrapping up
There you have it: a simple clock built with state-based UI. I'll be writing more articles like this, because I want to show that it's possible to use state-based UI without the overhead of a massive, bloated framework.
Feel free to check out the demo or view the full source code on GitHub. It's available under the MIT License. ❤️