简单理解DOM是什么?选择节点和遍历方法有哪些?

251 阅读2分钟

DOM是什么

操作文档 HTML 的 JS 处理方式为 DOM 即 Document Object Model 文档对象模型。如果对 HTML 很了解使用 DOM 并不复杂。

DOM怎么产生

  • 普通文档(.txt)和 HTML/XML文档(.html/*.xml)的区别仅仅是因为后者是有组织的结构化文件;
  • 浏览器将结构化的文档以树的数据结构读入浏览器内存,并将每个树的子节点定义为一个NODE(想象这颗树,从根节点到叶子节点都被建模为一个NODE对象); 这每个节点(NODE)都有自己的属性(名称、类型、内容...); NODE之间有层级关系(parents、child、sibling...);
  • 以上已经完成文档的建模工作(将文档内容以树形结构写入内存),此时再编写一些方法来操作节点(属性和位置信息),即为NODE API。

-->抽象一下:

DOM是一种将HTML/XML文档组织成对象模型的建模过程; DOM建模重点在于如何解析HTML/XML文档和开放符合DOM接口规范的节点操作API接口。

-->再抽象一下: 解析文档,建模成对象模型,开放API接口。

-->最后: 浏览器在加载页面是会生成 DOM 对象,以供我们使用 JS 控制页面元素。

image.png

DOM常用API有什么?

获取节点

1、getElement...(动态)

通过 getElementsByTagname 等 getElementsBy... 函数获取的 Nodelist 与 HTMLCollection 集合是的,即有元素添加或移动操作将实时反映最新状态。

动态特性

通过按钮动态添加元素后,获取的元素集合是动态的,而不是上次获取的固定快照。

2、querySelectorAll(静态)

document.querySelectorAll 获取的集合是静态的,比如

<h1>houdunren.com</h1>
<h1>houdunwang.com</h1>
<button id="add">添加元素</button>

<script>
  let elements = document.querySelectorAll('h1')
  console.log(elements.length)
  let button = document.querySelector('#add')
  button.addEventListener('click', () => {
    document.querySelector('body').insertAdjacentHTML('beforeend', '<h1>向军大叔</h1>')
    console.log(elements.length)
  })
</script>

页面添加多一个h1,但是elements不会动态更新。

遍历节点

forOf

Nodelist 与 HTMLCollection 是类数组的可迭代对象所以可以使用 for...of 进行遍历

<div id="houdunren">houdunren.com</div>
<div name="houdunwang">houdunwang.com</div>
<script>
  const nodes = document.getElementsByTagName('div')
  for (const item of nodes) {
    console.log(item)
  }
</script>

forEach

Nodelist 节点列表也可以使用 forEach 来进行遍历,但 HTMLCollection 则不可以\

补充:Nodelist 节点列表是什么?

(如使用 getElementsByClassName() 方法,某些(老的)浏览器会返回 NodeList 对象而不是 HTMLCollection。 大多数浏览器会为 querySelectorAll() 方法返回 NodeList 对象。)

借用 Array 的原型 map 方法

节点集合对象原型中不存在 map 方法,但可以借用 Array 的原型 map 方法实现遍历

<div id="houdunren">houdunren.com</div>
<div name="houdunwang">houdunwang.com</div>

<script>
  const nodes = document.querySelectorAll('div')
  Array.prototype.map.call(nodes, (node, index) => {
    console.log(node, index)
  })
</script>

当然也可以使用以下方式操作

;[].filter.call(nodes, node => {
	console.log(node)
})

借用Array.from

Array.from 用于将类数组转为组件,并提供第二个迭代函数。所以可以借用 Array.from 实现遍历

<div id="houdunren">houdunren.com</div>
<div name="houdunwang">houdunwang.com</div>

<script>
  const nodes = document.getElementsByTagName('div')
  Array.from(nodes, (node, index) => {
    console.log(node, index)
  })
</script>

展开语法

下面使用点语法转换节点为数组

<h1>houdunren.com</h1>
<h1>houdunwang.com</h1>
<script>
  let elements = document.getElementsByTagName('h1')
  console.log(elements)
  ;[...elements].map((item) => {
    item.addEventListener('click', function () {
      this.style.textTransform = 'uppercase'
    })
  })
</sc