Removing jQuery
Because everyone likes vanilla
In 2006, jQuery was released. It was quite a game changer, providing a terse syntax that allowed for quick front-end development, resulting in scripts that behaved consistently across browsers - in a time when Internet Explorer 6 was still king.
Fast forward 15 years, and jQuery is used by millions of web sites - paradoxally, in a time when web developers since long have considered jQuery a legacy library of the past. The browsers have definitely come a long way since 2006, and many of the problems that jQuery set out to solve may not actually be problems anymore. Modern JavaScript natively provides much of the functionality jQuery offers, and IE6 and the likes are long gone. So as an exercise, why not try to replace jQuery with plain JavaScript (AKA Vanilla JS) and see if that promise has come true? I did so on this very website and had some interesting findings. Read on for more.
Hint: I will be referring to plain, native ES6 JavaScript as "Vanilla JS" below.
Selecting HTML elements
Maybe the most used feature of jQuery: Selecting elements by ID, class name, tag name, and so on. Example:
// jQuery
var myElements = $(".active");
The code above would return all elements that have the CSS class
The native drop-in replacement would be:
// Vanilla JS
var myElements = document.querySelectorAll(".active");
Or, if you only need to select a single element:
// Vanilla JS
// Returns first match, or null if none was found
var myElement = document.querySelector(".active");
If we are selecting by class name, like above, we can also use (note that the dot is omitted):
// Vanilla JS
document.getElementsByClassName('active')
Selecting by ID is also just like jQuery, using the prefix "#":
// jQuery
var myElement1 = $("#myElement");
// Vanilla JS equivalent
var myElement2 = document.querySelector("#myElement");
// Also Vanilla JS equivalent
var myElement3 = document.getElementById("myElement");
A difference is that in jQuery, the returned elements will actually be jQuery objects, while the native
methods all return objects of type
Adding event handlers
Typically, we use
// jQuery
$("#myButton").on("click", function() {
console.log("Button was clicked");
}
Without jQuery, the equivalent code is:
// Vanilla JS
document.querySelector("#myButton").addEventListener("click", function() {
console.log("Button was clicked");
}
It's more verbose, but does about the same thing. Not quite the same thing however, which brings us to delegated event handlers.
Event handlers with event delegation
If the element that we want to attach the event handler to does not exist yet, we can still attach handlers to it using this technique in jQuery:
// jQuery
$("#dataTable tbody").on("click", "tr", () => {
console.log("Row was clicked");
});
This requires the data table body to exist, but not any rows. When the table is clicked, jQuery checks if the
We cannot do this natively, but a rather simple utility function does the trick (original source):
// Vanilla JS utility function for event delegation
function createDelegatedEventListener(selector, handler) {
return function (event) {
if (event.target.matches(selector) || event.target.closest(selector)) {
handler(event);
}
}
}
We can then use the function like this:
// Vanilla JS
document.querySelector("#dataTable tbody").addEventListener("click", createDelegatedEventListener("tr", (e) => {
console.log("Row was clicked");
// To get the clicked element:
const selectedRow = ev.target.closest("tr");
}));
So it works just fine - but I will admit, jQuery handles this really well and the native solution seems a bit clunky in comparison.
Adding the same event handler for multiple events
Sometimes we want to add the same event handler for when different events happen. For example, the code below adds an event handler that runs both when the user presses down the mouse button (typically desktop computer), as well as when the user starts a touch (typically mobile device):
// jQuery
$("#myButton").on("touchstart mousedown", function(e) {
console.log("Mouse button pressed or touch started");
});
While not as convenient, we can do this natively by a simple loop:
// Vanilla JS
for (const eventName of ["touchstart", "mousedown"]) {
document.querySelector("#myButton").addEventListener(eventName, (e) => {
console.log("Mouse button pressed or touch started");
});
}
Adding and removing CSS classes
Adding and removing CSS classes in jQuery is easy. And doing it natively is just about as easy! Here we add, remove and toggle the class
// jQuery
$("#myButton").addClass("active");
$("#myButton").removeClass("active");
$("#myButton").toggleClass("active");
// Vanilla JS
document.querySelector("#myButton").classList.add("active");
document.querySelector("#myButton").classList.remove("active");
document.querySelector("#myButton").classList.toggle("active");
Hint: Both toggle methods accept an additional boolean parameter that adds the class if
Also, to check if an element has a certain CSS class, we can do this:
// jQuery
$("#myButton").hasClass("active")
// Vanilla JS
document.querySelector("#myButton").classList.contains("active")
Getting the size of the window
With jQuery, the (unit less) width and height of the current window can be retrieved by:
// jQuery
var width = $(window).width();
var height = $(window).height();
Getting these values natively is as easy and:
// Vanilla JS
var width = window.innerWidth;
var height = window.innerHeight;
Similarly, setting the width of an element with jQuery can be done like this:
// jQuery
$("#myElement").width("100px");
This can be replaced by:
// Vanilla JS
document.querySelector("#myElement").style.width = "100px";
AJAX/XHR requests
I have seen projects where jQuery is used for handling network requests and then not much else. In such cases, it might be attractive to look at the Vanilla JS alternative
Here is a very simple
// jQuery
$.get("/api/comments/1", function(data) {
console.log("Data retrieved from server.");
});
And the equivalent in Vanilla JS:
// Vanilla JS
fetch("/api/comments/1")
.then(function(response) { return response.json(); })
.then(function(data) {
console.log("Data retrieved from server.");
});
Note that after we get the response, the body needs to be read with
Sending a
// jQuery
$.post('/api/comments', data, function(result) {
console.log("Data sent to server.");
}, 'json')
.fail(function(xhr) {
console.log("Error sending data.");
});
In Vanilla JS, the code is a bit more involved. We both need a
// Vanilla JS
fetch('/api/comments',
{
method: 'POST',
body: JSON.stringify(data)
}).then(function (response) {
if (!response.ok) {
console.log("Did not get OK code from server.");
} else {
response.json().then(function(result) {
console.log("Data sent to server.");
});
}
}).catch((error) => {
console.log("Network error sending request.")
});
Fading
Fading out an element in jQuery is super easy:
// jQuery
$("#myElement").fadeOut(200, function() {
console.log("Fade out complete.");
});
Without jQuery, we have a few different options. You might create a CSS class that animates the element and then remove it. We can also create a utility function that animates and then hides the element:
// Vanilla JS: Utility function that basically does what jQuery.fadeOut does.
fadeOut = function(element, duration, callback) {
element.animate({
opacity: 0
}, {
duration: duration,
easing: "linear",
iterations: 1,
fill: "both"
})
.onfinish = function() {
element.style.display = "none";
if (callback) {
callback();
}
}
}
// This is how we call the utility function.
fadeOut(document.querySelector('#myElement'), 200, () => {
console.log("Fade out complete.");
});
Conclusion
I was pleasantly surprised to find that I could indeed remove jQuery without all too much hassle. Much of the functionality of jQuery has simple replacements (such as
Would I recommend removing jQuery just because it's possible? That depends. The minified version of jQuery is around 30kB at the moment and is unlikely to make much of a difference to load times on most sites. However, it could be a good idea to stop developing anything new with jQuery and look at other options first. For simpler systems, Vanilla JS might just be the right tool for the job.
Still, I kept jQuery as well as jQuery UI on the old Icon Maker page. While it matters little in my case, it still demonstrates maybe the biggest hurdle: If you have built a rather involved app using jQuery, and especially jQuery UI, migrating away from that may realistically mean that you need a rewrite. As always, your mileage may vary.
Hint: When switching from jQuery to Vanilla JS, first check Can I use... to make sure that the browsers that you are targeting support the functionality natively.
0 Comments
Subscribe to new comments by RSS