Replacing jQuery with Vanilla JavaScript
bob.ts
Posted on November 11, 2021
For many years, it seemed as if jQuery had become synonymous with JavaScript. Since its introduction in 2006, jQuery caused a revolution in front-end scripting.
jQuery is still a useful library. With broad browser support of ES6, now is probably a good time to move away from jQuery.
One of the reference sites I like (because of the side-by-side replacement options) is You Might Not Need jQuery.
Index
- Document Ready
- Selecting Elements
- Working with Classes
- Working with Events
- Network Requests
- Updating the DOM
Document Ready
To wait for the DOM to fully load, jQuery used $(document).ready()
or the common short-hand $()
in jQuery. This can easily be constructed in a similar function to replace it with by listening to DOMContentLoaded
.
// With jQuery
$(document).ready(function() {
/* Do things after DOM has fully loaded */
});
// Without jQuery
const onReady = (callback) =>{
if (document.readyState!='loading') callback();
else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
else document.attachEvent('onreadystatechange', function() {
if (document.readyState=='complete') callback();
});
};
ready(() => {
/* Do things after DOM has fully loaded */
});
Selecting Elements
Selecting one or several DOM elements to do something with is one of the most basic elements of jQuery. The equivalent to $()
or jQuery()
in JavaScript is querySelector()
or querySelectorAll()
, which can be called with a CSS selector.
// jQuery, select all instances of .item
$('.item');
// Instead, select the first instance of .item
document.querySelector('.item');
// ... or, select all instances of .item
document.querySelectorAll('.item');
Acting on All Elements in a Selection
querySelectorAll()
returns a NodeList containing all of the elements matching the query. JavaScript needs to iterate over the NodeList of elements using NodeList.forEach()
in vanilla JavaScript.
// With jQuery
$('.item').hide();
// Without jQuery
document.querySelectorAll('.item').forEach(item => {
item.style.display = 'none';
});
Finding an Element within Another
A common jQuery pattern is to select an element within another element using .find()
. The same effect can be achieved by scoping the selection to an element’s children, by calling querySelector
or querySelectorAll
on an element.
// With jQuery
const container = $('.wrapper');
container.find('.item');
// Without jQuery
const container = document.querySelector('.wrapper');
container.querySelector('.item');
Traversing the DOM Tree
To traverse the DOM, select a sibling or a parent element relative to another element through nextElementSibling
, previousElementSibling
and parentElement
.
// With jQuery
$('.item').next();
$('.item').prev();
$('.item').parent();
// Without jQuery
const item = document.querySelector('.item');
item.nextElementSibling;
item.previousElementSibling;
item.parentElement;
Styling Elements
When calling .css()
on an element to change its inline CSS with jQuery, use .style
in JavaScript and assign values to its different properties to achieve the same effect.
// With jQuery
$('.item').css('color', '#000');
// Without jQuery
document.querySelector('item').style.color = '#000';
With jQuery, pass an object with key-value pairs to style many properties at once. In JavaScript, set the values one at a time, or set the entire style string.
// With jQuery
$('.item').css({
'color': '#000',
'background-color': 'red'
});
// Without jQuery
const item = document.querySelector('.item');
item.style.color = '#000';
item.style.backgroundColor = 'red';
// Set all styles at once (and override any existing styles)
item.style.cssText = 'color: #000; background-color: red';
Creating Elements
To dynamically create an element in JavaScript and add it to the DOM, can call createElement()
and pass it a tag name to indicate what element to create.
// Create a div and span
$('<div/>');
$('<span/>');
// Create a div and a span
document.createElement('div');
document.createElement('span');
To add some content to those elements, simply set the textContent
property, or create a text node with createTextNode
and append it to the element.
const element = document.createElement('div');
element.textContent = 'Text';
const text = document.createTextNode('Text');
element.appendChild(text);
Working with Classes
The code can easily access and work with classes through the classList
property to toggle
, replace
, add
, and remove
classes.
// With jQuery
$('.item').addClass('focus');
$('.item').removeClass('focus');
$('.item').toggleClass('focus');
// Without jQuery
const item = document.querySelector('.item');
item.classList.add('focus');
item.classList.remove('focus');
item.classList.toggle('focus');
To remove or add multiple classes, just pass multiple arguments to .add()
and .remove()
.
// Add focus and highlighted classes, then remove
const item = document.querySelector('.item');
item.classList.add('focus', 'highlighted');
item.classList.remove('focus', 'highlighted');
When toggling two classes that are mutually exclusive, access the classList
property and call .replace()
to replace one class with another.
// Remove the focus class and add blurred
document.querySelector('.item').classList.replace('focus', 'blurred');
Checking if an Element has a Class
To run a function if an element has a certain class, replace jQuery’s .hasClass()
with .classList.contains()
.
// With jQuery
if ($('.item').hasClass('focus')) {
// Do something...
}
// Without jQuery
if (document.querySelector('.item').classList.contains('focus')) {
// Do something...
}
Working with Events
There are many ways to listen to events in jQuery, but whether using .on()
, .bind()
, .live
or .click()
, make do with the JavaScript equivalent .addEventListener
.
// With jQuery
$('.button').click(function(e) {
/* handle click event */
});
$('.button').mouseenter(function(e) {
/* handle click event */
});
$(document).keyup(function(e) {
/* handle key up event */
});
// Without jQuery
document.querySelector('.button').addEventListener('click', (e) => {
/* ... */
});
document.querySelector('.button').addEventListener('mouseenter', (e) => {
/* ... */
});
document.addEventListener('keyup', (e) => {
/* ... */
});
Listening for Dynamically Added Elements
jQuery’s .on()
method works with live event handlers that listen to events on objects that get dynamically added to the DOM. To accomplish something similar without jQuery, attach the event handler on an element as it is added to the DOM.
// With jQuery
$('.search-container').on('click', '.search-result', handleClick);
// Without jQuery
const searchElement = document.createElement('div');
document.querySelector('.search-container').appendChild(searchElement);
searchElement.addEventListener('click', handleClick);
Triggering and Creating Events
The equivalent to manually triggering events with trigger()
can be achieved by calling dispatchEvent()
. The dispatchEvent()
method can be invoked on any element, and takes an Event as the first argument.
// With jQuery
$(document).trigger('myEvent');
$('.item').trigger('myEvent');
// Without jQuery
document.dispatchEvent(new Event('myEvent'));
document.querySelector('.item').dispatchEvent(new Event('myEvent'));
hide()
and show()
The .hide()
and .show()
functions are convenience methods that are equivalent to accessing the .style
property and setting display: none;
and display: block;
.
// With jQuery
$('.item').hide();
$('.item').show();
// Without jQuery
document.querySelector('.item').style.display = 'none';
document.querySelector('.item').style.display = 'block';
Network Requests
fetch()
creates a network request in a similar fashion to jQuery’s ajax()
and get()
methods. fetch()
takes a URL as an argument, and returns a Promise that can be used to handle the response.
// With jQuery
$.ajax({
url: 'data.json'
}).done(function(data) {
// ...
}).fail(function() {
// Handle error
});
// Without jQuery
fetch('data.json')
.then(data => {
// Handle data
}).catch(error => {
// Handle error
});
Updating the DOM
To change the text of an element or to add new elements to the DOM innerHTML()
comes to mind, but using it may expose the code to cross-site scripting (XSS) attacks. There are some safer alternatives.
To read or update the text of an element, use the textContent
property of an object to return the current text, or update it ...
// With jQuery
$('.button').text('New text');
$('.button').text(); // Returns 'New text'
// Without jQuery
document.querySelector('.button').textContent = 'New text';
document.querySelector('.button').textContent; // Returns 'New text'
When constructing a new element and add that element to another element by using the method on the parent appendChild()
...
// Create div element and append it to .container
$('.container').append($('<div/>'));
// Create a div and append it to .container
const element = document.createElement('div');
document.querySelector('.container').appendChild(element);
Put together, here is how to create a div, update its text and class, and add it to the DOM ...
const element = document.createElement('div');
element.classList.add('item');
element.textContent = 'Text inside item.';
document.querySelector('.container').appendChild(element);
Summary
jQuery caused a revolution in front-end scripting and it is still a useful library. However, with broad browser support of ES6, now is probably a good time to move away from jQuery.
We have covered: Document Ready, Selecting Elements, Working with Classes, Working with Events, Network Requests, and Updating the DOM. These six major categories cover much of what jQuery was used to implement.
Posted on November 11, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.