课程来源:B站后盾人

有关DOM的介绍

在此引用一位大佬的博客的部分内容:
JS-DOM
https://blog.csdn.net/weixin_45077672/article/details/116693698?spm=1001.2014.3001.5501

1.什么是DOM

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容,结构和样式。

2.DOM树


文档:一个页面就是一个文档,DOM中使用document表示
元素:页面中所有标签都是元素,DOM中使用element表示
节点:网页中所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
DOM把以上内容都看做是对象


困扰新手的DOM加载问题

3.html
如果不加defer="defer",会找不到元素

<!DOCTYPE html>
<html lang="en">
    <head>
        <!-- defer:内容渲染之后再来执行脚本内容 -->
        <script src="3.js" defer="defer"></script>
    </head>
    <body>
        <h2 id="hd">houdunren.com</h2>
    </body>
</html>

3.js

const el = document.getElementById('hd')
console.log(el)

运行结果:

如果不加呢?

因为在页面渲染之前就加载了js,这个时候是找不到这个元素的.
将js语句放在body内的最下面试一试:

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- defer:内容渲染之后再来执行脚本内容 -->
  </head>
  <body>
    <h2 id="hd">houdunren.com</h2>
    <script src="3.js" defer="defer"></script>
  </body>
</html>

运行结果:

可见这个方法是可行的.


节点node的概念

  • 所有东西都是节点,标签,属性,文本,均是节点(Node)
  • document.是节点的起始,节点是一个树状的关系
  • document.childNodes是所有的子节点

4.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <h2>houdunren.com</h2>
    <!-- 注释也是节点哦 -->
    <script> // console.log(document.childNodes[1].childNodes) const h1 = document.childNodes[1].childNodes[2] // 节点类型是用数字进行表示的 console.log('document.nodeType:', document.nodeType) console.log('h1.childNodes[0].nodeType:', h1.childNodes[0].nodeType) console.log('h1.childNodes[0]:', h1.childNodes[0]) console.log('h1.childNodes[1].nodeType:', h1.childNodes[1].nodeType) console.log('h1.childNodes[1]:', h1.childNodes[1]) //h1.childNodes包含些什么?定义的h1到底是啥?打印出来看一下,似乎是整个body 的内容~ console.log('h1.childNodes:', h1.childNodes) </script>
  </body>
</html>

运行结果:

容易忘记的是文本,注释也是节点


Node 节点对象的原型继承

重点看代码和console的输出
5.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>后盾人</title>
  </head>
  <body>
    <h2 id="h2 id here">houdunren.com</h2>
    <input type="text" id="inputId" value="后盾人" />
  </body>
</html>

我把script标签部分单独提出来,这样看起来直观一些.
可以分别关注body内有什么,再看看脚本里写了什么.
body内:一个h2标签,一个input标签.

<script> // h2 是一个对象 const h2 = document.querySelector('h2') // 找它的原型对象:两种方法 console.log('Object.getPrototypeOf(h2):', Object.getPrototypeOf(h2)) console.log('h2.__proto__:', h2.__proto__) function prototype(el) {
      const prototypes = [] prototypes.push(el.__proto__) // 为空就不用找了,"..."是解构赋值,展开结果. prototypes.push(...(el.__proto__ ? prototype(el.__proto__) : [])) return prototypes } console.log('prototype(h2):', prototype(h2)) console.log('h2.id:', h2.id) const input = document.querySelector('input') console.log('prototype(input):', prototype(input)) </script>
  • const h2 = document.querySelector('h2')是获取h2标签
  • 下面有找它的原型的方法,但是都比较老旧,并不这么用
  • .push():往这个数组末尾添加一个新的项
  • ...:解构赋值:就是把它里面的东西展开
  • 如果el.__proto__为空还要找,就会报错.

运行结果:

把h2改成h1:看看报错


通过prototype原型操作节点元素

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>通过prototype原型操作节点元素</title>
  </head>
  <body>
    <h2 onclick="this.color('red')">houdunren.com</h2>
    <h1 onclick="this.hide()">向军</h1>
    <div onclick="this.color('blue')">this is div element</div>

    <script> const h2 = document.querySelector('h2') const h1 = document.querySelector('h1') Node.prototype = Object.assign(Node.prototype, {
      color(color) {
      // this代表当前触发这个事件的对象 this.style.color = color }, hide() {
      this.style.display = 'none' }, }) console.log('h2.__proto__:', h2.__proto__) console.log('h1.__proto__:', h1.__proto__) // 东西没了,也不会报错 </script>
  </body>
</html>
  • 观察:body里一共有3个元素一个h2,一个h1,和一个div
  • this代表当前触发这个事件的对象

运行结果:(点击前)

点击后