Replacing jQuery with Vanilla JavaScript

bob.ts - Nov 11 '21 - - Dev Community

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

  1. Document Ready
  2. Selecting Elements
  3. Working with Classes
  4. Working with Events
  5. Network Requests
  6. 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 */ 
});
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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';
});
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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...
}
Enter fullscreen mode Exit fullscreen mode

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) => {
  /* ... */
});
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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'));
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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
  });
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .