The original

DOM manipulation is not as difficult as you might think.

A preliminary introduction

Many Web developers think DOM is really hard (or slow) and that you need a lot of frameworks to tame it. Then they spend a lot of time learning the framework, and after a year or two, another framework becomes popular, and you have to learn everything from scratch. Repeat this a few times, and JavaScript fatigue sets in. Not to mention a whole lot of dependencies. Would you believe me if I told you DOM wasn’t that difficult? If it’s cool not to have to rely on third-party libraries to master DOM, would you give DOM a second chance? Let’s take a look:

DOM is not that hard and especially not slow.

First, I’ll show you some basic techniques from my own personal library RE:DOM

Create the element

To create an HTML element, you need to use the document.createElement(tagName) method:

const h1 = document.createElement('h1')
// 

Copy the code

Modify text content

If the HTML element has no content, it is empty:

h1.textContent = 'Hello world! '/ /

Hello world!

Copy the code

Attributes

h1.setAttribute('class', 'hello')
// 

Hello world!

Copy the code

To manage classes, use the element.className attribute

h1.className = 'hello'
// 

Hello world!

Copy the code

However, the best way is to use classList

h1.classList.add('hello')
// 

Hello world!

h1.classList.remove('hello') //

Hello world!

Copy the code

To set the ID of an element, you can use attribute or set the ID attribute directly


h1.setAttribute('id', 'hello-world')
h1.id = 'hello-world'
// 

Hello world!

Copy the code

If you’re unsure whether to use Attributes or properties, use Attributes, in addition to form element states like Value and Checked

You cannot use element.setAttribute(someBoolean, false) to set bool values except for the following:

input.checked = true
// 
input.checked = false
// Input. SetAttribute (" checked ", "') / /
input.removeAttribute('checked')
// Copy the code

Add elements

document.body.appendChild(h1)
// 

Hello world!

Copy the code

Remove elements

document.body.removeChild(h1)
// Copy the code

Look for the element

  • document.getElementById(id)
  • element.childNodes[i]
  • element.firstChild === element.childNodes[0]
  • element.lastChild === element.childNodes[element.childNodes.length – 1]
  • element.getElementsByTagName(tagName)
  • element.getElementsByClassName(className)
  • element.querySelector(query)
  • element.querySelectorAll(query)

Note: GetElementsByTagName, getElementsByClassName, and querySelectorAll return not an array, but a NodeList, so you can’t iterate with ES5’s array iterator. Here’s a little bit about NodeList

Insert elements between elements

/*
 *  
 *    
 *  
 */
 document.body.insertBefore(h1, document.body.firstChild)
/*  
 *    

Hello world!

* * * /Copy the code

Create a lot of elements


const data = [
  [ 1, 2, 3 ],
  [ 4, 5, 6 ],
  [ 7, 8, 9 ]
  ]
const table = document.createElement('table')
data.forEach(row => {
  const tr = document.createElement('tr')
  row.forEach(cell => {
    const td = document.createElement('td')

    td.textContent = cell
    tr.appendChild(td)
 })
  table.appendChild(tr)
  })
document.body.appendChild(table)Copy the code

Update a set of elements

const table = document.createElement('table') document.body.appendChild(table) updateTable(table, [ [ 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8, 9 ] ]) setTimeout(() => { updateTable(table, [ [ 1, 2, 3, 4 ], [ 5, 6, 7 ], [ 8, 9 ] ]) }, 1000) function updateTable (table, data) { const rowLookup = table._lookup || (table._lookup = []) setChildren(table, updateRows(rowLookup, data)) } function updateRows (rowLookup, rows) { return rows.map((row, y) => { const tr = rowLookup[y] || (rowLookup[y] = document.createElement('tr')) const cellLookup = tr._lookup || (tr._lookup = []) setChildren(tr, updateCells(cellLookup, row)) return tr }) } function updateCells (cellLookup, cells) { return cells.map((cell, x) => { const td = cellLookup[x] || (cellLookup[x] = document.createElement('td')) td.textContent = cell return td }) } function setChildren (parent, children) { let traverse = parent.firstChild for (let i = 0; i < children.length; i++) { const child = children[i] if (child == null) { return } if (child === traverse) { traverse = traverse.nextSibling  } else if (traverse) { parent.insertBefore(child, traverse) } else { parent.appendChild(child) } } while (traverse) { const next = traverse.nextSibling parent.removeChild(traverse) traverse = next } }Copy the code

What kind of magic is this? Two things are happening here:

  • 1. There is a hidden element, element._lookup = [], which looks for child elements (possibly an element with an ID) and uses this method to reuse existing DOM and update them
  • 2. The setChildren(parent, children) method has a list of child elements

You can also mount/unmount child elements using the setChildren method

setChildren(login, [
  email,
  !forgot && pass
  ])Copy the code

Followed by an AD for the author’s RE:DOM.