十一、节点属性 type,tag 和 content

11.1 DOM 节点类

不同的 DOM 节点可能有不同的属性,但是这些 DOM 之间存在共有的属性和方法,所有类型的 DOM 节点都形成一个单一层次的结构。

每个 DOM 节点都属于相应的内置类。

  • EventTarget —— 根的抽象类。该类的对象从未被创建,它是一个基础,以便让所有节点都能够支持事件。
  • Node —— 抽象类,是 DOM 节点的基础,它提供了 DOM 节点的一些属性:nextSibling,parentNode等。
  • Element —— DOM 元素的基本类,它提供元素的导航,即:nextElementSibling和children等属性。
  • HTMLElement —— 所有 HTML 元素的基本类。各种 HTML 元素继承于它:
    • HTMLInputElement —— input 元素的类
    • HTMLBodyElement —— body 元素的类
    • 每个标签都可以有自己的类,这些类都有指定属性和方法
image-20220108231040580

因此,节点的全部属性和方法都是继承的结果。

DOM 节点是常规的 JavaScript 对象,它们使用基于原型的类进行继承。

我们可以通过console.dir来探究 DOM 节点的属性

11.2 nodeType 属性

这是一种过时的获取节点类型的方法。

  • 元素节点elem.nodeType===1
  • 文本节点elem.nodeType===3
  • document 对象 elem.nodeType===9

现在,我们可以通过instanceof或者其他基于类的方法来判断节点类型。

javascript
1instanceof HTMLBodyElement
2instanceof HTMLInputElement

11.3 nodeName 和 tagName

nodeName 和 tagName 都可以返回元素的标签名。

它们的区别在于nodeName是任意 Node 定义的,而tagName仅属于Element节点

11.4 InnerHTML 内容

innerHTML属性允许将元素内的 HTML 用字符串的形式返回出来。

同时,我们也可以用它以字符串的形式来设置节点内的 HTML。

javascript
1document.body.innerHTML = '<button>我被设置了</button>'

如果我们用 innerHTML 在页面上设置一个 script 标签,它并不会运行。

当我们用innerHTML+=‘...’添加内容时,它实际的工作是这样的:

  • 移除旧的内容
  • 写入新的 innerHTML(新旧结合)

因为内容已“归零”并从头开始重写,因此所有的图片和其他资源都将重写加载。

并且还会有其他副作用。例如,如果现有的文本被用鼠标选中了,那么大多数浏览器都会在重写 innerHTML 时删除选定状态。如果这里有一个带有用户输入的文本的 <input>,那么这个被输入的文本将会被移除。诸如此类。

11.5 outerHTML 元素的完整 HTML

outerHTML 包含元素的完整 HTML。就像 innerHTML 加上元素自身一样。

html
1<div id="elem">Hello <b>World</b></div>
2
3<script>
4  alert(elem.outerHTML) // <div id="elem">Hello <b>World</b></div>
5</script>

注意:与 innerHTML 不同,写入 outerHTML 不会改变元素。而是在 DOM 中替换它。

html
1<div>Hello, world!</div>
2
3<script>
4  let div = document.querySelector('div')
5
6  // 使用 <p>...</p> 替换 div.outerHTML
7  div.outerHTML = '<p>A new element</p>' // (*)
8
9  // 蛤!'div' 还是原来那样!
10  alert(div.outerHTML) // <div>Hello, world!</div> (**)
11</script>

在 (*) 行,我们使用 <p>A new element</p> 替换 div。在外部文档(DOM)中我们可以看到的是新内容而不是 <div>。但是正如我们在 (**) 行所看到的,旧的 div 变量并没有被改变。

outerHTML 赋值不会修改 DOM 元素(在这个例子中是被 ‘div’ 引用的对象),而是将其从 DOM 中删除并在其位置插入新的 HTML。

所以,在 div.outerHTML=... 中发生的事情是:

  • div 被从文档(document)中移除。
  • 另一个 HTML 片段 <p>A new element</p> 被插入到其位置上。
  • div 仍拥有其旧的值。新的 HTML 没有被赋值给任何变量。

在这儿很容易出错,我们可以向 elem.outerHTML 写入内容,但是要记住,它不会改变我们所写的元素(‘elem’)。而是将新的 HTML 放在其位置上。我们可以通过查询 DOM 来获取对新元素的引用。

11.6 nodeValue/data:文本节点内容

innerHTML 仅对元素节点有用,如果我们想获取其他节点的内容,可以使用 nodeValue/data。这两个几乎没有差别。一般我们用 data,因为它更短。

html
1<body>
2  Hello
3  <!-- Comment -->
4  <script>
5    let text = document.body.firstChild
6    alert(text.data) // Hello
7
8    let comment = text.nextSibling
9    alert(comment.data) // Comment
10  </script>
11</body>

11.7 textContent :纯文本

我们能够使用textContent读写元素内的纯文本,而不包含<tags>

html
1<div id="news">
2  <h1>Headline!</h1>
3  <p>Martians attack people!</p>
4</div>
5
6<script>
7  // Headline! Martians attack people!
8  alert(news.textContent)
9</script>

如果我们希望写入的类似这样的字符串<a>123</a>被当做文本插入元素中,而不是被当做 HTML 插入,那么对elem.textContent进行赋值可以完成这样的需求。

11.8 hidden 属性

hidden 是 DOM 属性,也是 HTML 的特性。它指定元素是否可见。

它的作用类似display:hidden,但是它更简短。

javascript
1element.setAttribute('hidden', '') //设置hidden特性
2element.hidden = true //设置hidden属性

11.9 小结

每个 DOM 节点都属于特定的类,这些类形成一个层次结构。完整的属性和方法是继承后的结果。

主要的 DOM 节点属性:

  • nodeType 节点类型
  • nodeName/tagName 节点名/标签名
  • innerHTML 元素的 HTML 内容,可读写
  • outerHTML 元素包括自己的 HTML 内容,可读写。但写入只是替换新的 HTML。
  • nodeValue/data 非元素节点获取内容,可以读写
  • textContent 元素的纯文本内容,可读写
  • hidden 相当于display:none,但更简洁。
  • ...其他