掌控 DOM - 它不像你想的那末难

许多开发者以为 DOM 是真的很难(或许很慢)以至于你须要一个庞大的框架才能让它帖服。因而他们投入了大批的时候去进修这些框架。一两年过去了,又一个框架火了因而你不能不抛弃之前的框架重新学起。如许的事变多反复频频就能让你对 JavaScript 发作委靡,更不用说那多的数不过来的依靠。

假如我通知你 DOM 实在没那末庞杂,你信吗?

DOM 并不难而且它也不慢。

建立元素

要建立一个元素,你只须要写 document.createElement(tagName)

const h1 = document.createElement('h1')

// <h1></h1>

修正文本内容

HTML 元素假如没有任何内容,那就是空的,让我们用 element.textContent 来增添一些文本

h1.textContent = 'Hello world!'

// <h1>Hello world!</h1>

属性

要定义一个 HTML 元素的属性,你能够用 element.setAttribute(name, value)

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

// <h1 class="hello">Hello world!</h1>

若要治理 class 有一个 element.className 属性

h1.className = 'hello'

// <h1 class="hello">Hello world!</h1>

然则,最好的体式格局是运用 classList

h1.classList.add('hello')

// <h1 class="hello">Hello world!</h1>

h1.classList.remove('hello')

// <h1>Hello world!</h1>

要设置一个元素的 ID,你能够运用标签属性或许 id 属性

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

h1.id = 'hello-world'

// <h1 id="hello-world" class="hello">Hello world!</h1>

假如你不确定用标签属性(attributes)照样对象属性(properties),就用标签属性 (表单元素的状况除外,如 value 和 checked)

注重,有些布尔值的修正不能运用 element.setAttribute(someBoolean, false),下面这些则能够

input.checked = true

// <input checked>

input.checked = false

// <input>

input.setAttribute(‘checked’, ‘’)

// <input checked>

input.removeAttribute('checked')
// <input>

元素附加

HTML 是结构化的。能够经由过程 parent.appendChild(child) 来完成元素附加

document.body.appendChild(h1)

// <body><h1>Hello world!</h1></body>

元素移除

有时候你愿望去掉一个元素,那末你能够运用 parent.removeChild(child)

document.body.removeChild(h1)

// <body></body>

元素查找

你能够运用以下要领来查找子元素

  • 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)

注重 getElementsByTagName, getElementsByClassName 和 querySelectorAll 返回的不是数组,而是 NodeList,你不能经由过程 ES5 的数组疾速接见体式格局来迭代。

元素间插进去元素

想要将元素查到另一个元素的前面?尝尝 parent.insertBefore(child, before)

/*

 *  <body>

 *    <script src="main.js"></script>

 *  </body>

 */

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

/*  <body>

 *    <h1>Hello world!</h1>

 *    <script src="main.js"></script>

 *  </body>
 */

建立元素列表

假如我们有一些数据,能够很轻易的动态建立元素。

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)

https://jsfiddle.net/pakastin…

更新元素列表

你愿望元素坚持最新状况,能够这么做

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
  }
}

https://jsfiddle.net/pakastin…

以上代码有两个事变发作

  1. 一个隐蔽属性 element._lookup = [] 用来查找子元素,运用lookup 我们能够复用DOM中已存在的元素并更新它们。

  2. setChildren(parent, children) 要领能让你供应一个元素列表。它很智慧的和已附加在 parent的元素举行比较并按需举行 插进去 移除 重排等操纵

    原文作者:王铁手
    原文地址: https://segmentfault.com/a/1190000007800333
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞