[Definitions: "Vanilla JS" = plain old JavaScript with no framework, and no build tools etc., "Big-framework-X" = React, VueJS, Angular, Svelte, etc.]
When building light weight interactivity on a webpage, I often find myself in this space between doing it in Vanilla JS or pulling out my big-framework-X of choice.
Mini-frameworks like AlpineJS, Vue-Petite, and Stimulus exist exactly to fill this space. But whenever I consider reaching for one of these, I usually find that the job can just as easily be done in Vanilla JS. And if it can't, it typically requires the big-framework-X anyway.
Vanilla JS is of course much simpler, ships less bytes to users, and consumes fewer CPU cycles from user devices. And with Vanilla JS my development setup is much simpler too (no npm, bundlers, build-tools, etc. needed).
Here are 4 small tips that might make you choose Vanilla JS more often:
Tip 1 - Use element IDs directly in JS code
When big-framework-X code is compared to vanilla JS, you will often see the vanilla JS sample code littered with document.getElementById(...)
or document.querySelector(...)
statements (making the Vanilla JS version look bloated). This is pure propaganda. There is no need for this. For simple stuff (where you would typically use vanilla JS), you can just reference HTML elements using their IDs directly in JS:
<input type=checkbox id=MyChk1>
<script>
MyChk1.checked = true;
</script>
Tip 2 - Use "hidden" for conditionals
One reason that you might use big-framework-X is conditionals - some syntax which renders a section of HTML to the DOM - or not - depending on some condition. A simple Vanilla JS alternative to this is the "hidden" attribute / property. To show/hide a div (and its content), you can simply do this:
<div id=MyDiv1 hidden>...</div>
<div id=MyDiv2>...</div>
<script>
// swap which divs are visible
MyDiv1.hidden = false;
MyDiv2.hidden = true;
</script>
Tip 3 - Template Literals
Another reason that you might use big-framework-X is templating (like React's JSX or Vue's SFC). Vanilla JS actually comes with a powerful templating system called template literals, which can be utilized in much the same way.
<div id=MyDiv1></div>
<script>
let Title='Shopping list';
let Items=['Apples','Bananas','Dog food'];
MyDiv1.innerHTML=`<h1>${Name}</h1>
<ul>
${Items.map(itm=>`<li>${itm}</li>`).join('')}
<ul>`;
</script>
Tip 4 - Inline event handlers
You may have been taught that inline event handlers are bad, and that you need to use element.addEventListener(...)
instead. You will often see this when big-framework-X code is compared to vanilla JS (making the Vanilla JS version look bloated).
Once again, this is pure propaganda. For simple stuff (where you would typically use vanilla JS), inline event handlers are perfectly fine, much simpler, terse and readable.
<div id=MyDiv1>...</div>
<input type=checkbox onclick="MyDiv1.hidden=this.checked">
Combining all 4
I re-created the obligatory (for big JS frameworks) To Do List application in Vanilla JS combining above techniques:
Fully functional, yet simple and short, and it can easily compete with big-framework-X.