As a fellow web dev you’re probably separating your HTML and JavaScript layers following the holy peanut strategy we all love. This separation is classically done based on CSS classes. In this article I’ll compare this classic bind-on-class-name method with the new and improved bind-on-data-attribute method.
Let’s take a look at the classic class name example.
The Foo, Bar and Baz files all register their JavaScript classes with the same name on the global scope. So for “Foo.js” this would be window.Foo
.
Alright, let’s look at the initialisation logic.
In the example, we’re binding our JavaScript using CSS classes. By prefixing those with js-
we’re making clear to other developers that these classes are JavaScript related.
Our initialisation script queries the DOM for each available class name. The elements in the returned nodelists are then used to initialise the various JavaScript modules.
Works fine right? Well, it does, but, using the above setup, your logic needs to know the names of each CSS class and each and everyone of the JavaScript modules.
Let’s give this a shot using data attributes and examine the differences.
We fetch all nodes matching having a data-module
attribute. While looping over those nodes we get the name of the module from the data-module
attribute itself and then reference it on the global scope (window[name]
). Done. Single loop.
While our classic getElementsByClassName
method performs a little bit better than the querySelectorAll
method the later unlocks advantages that outweigh this performance difference.
- Your JavaScript does not need know about the specific modules it might have to load, it gets the names from the HTML itself. Also, there’s no class names, your JavaScript only has to check for the
data-module
attribute, that’s it. - Looking at the HTML it’s crystal clear which part of the DOM is or will be enhanced with JavaScript functionality. It will always be in the form of a
data-module
attribute. - Because the modules are loaded in a single loop the order in which the modules load is out of your control. Meaning you’ll have to improve your code to better test if everything is ready for a module to load.
- Once you’ve got this setup, you never have to touch it again, with the classic class name version you have to keep adding loops for each new functionality.
- You can easily take this to the next level by defining modules using UMD. This way you can load your module async using a module loader with the advantage that you’ll no longer have to embed the
<script>
tag manually. Total separation.
The above is a stepping stone. Because of a better separation of concerns you’ll force yourself to think more modular. This results in cleaner, more reusable and maintainable code.
Give data attributes a go, you’ll never look back!