JS知识点梳理(7)-DOM

DOM(文档对象模型)是针对 HTML 或 XML 文档的一个 API,它描绘了一个层次化的节点数,允许开发人员添加、移除、修改页面的某一部分。

节点层次

  • DOM 将 HTML 或 XML 文档描绘成一个由多次层节点构成的结构
  • 节点由不同类型,每种类型分别表示文档中不同的信息或标记;每个节点都有各种的特点、数据、方法,并与其他节点存在某种关系。
  • 节点之间的关系构成了层次,所有页面标记表现为一个以特定节点为根节点的树形结构
  • 文档节点 是每个文档的根节点。每个文档只要一个文档元素,在 HTML 中,文档元素始终是<html>元素

Node 类型

  • DOM 中定义一个 Node 接口,该接口由 DOM 中所有节点类型实现。
  • JavaScript 中所有节点类型(12 种)都继承自 Node 类型

Node 属性

  • Node.nodeType, 返回该节点类型所有对应的数值常量(12 种)
    Node.nodeType

  • Node.nameName, 返回包含该节点名字的DOMStringHTMLElement节点的对应元素的标签名(),Text节点 对应的是"#text"Document节点对应的是"#document".

  • Node.nodeValue,返回或设置当前节点的值

  • Node.childNodes,返回该节点的所有子节点的实时的NodeLis.即 NodeList 是动态变化的,如果该节点的子节点发生变化,NodeList 对象会自动更新

  • Node.parentNode,返回该节点的父节点Node,没有则为null

  • Node.firstChild,返回该节点的第一个子节点Node,没有则为null

  • Node.lastChild,返回该节点的最后一个子节点Node,没有则为null

  • Node.nextSibling,返回该节点同辈的下一个节点Node,没有则为null

  • Node.previousSibling,返回该节点同辈的前一个节点Node,没有则为null

  • Node.ownerDocument,返回该节点属于的Document对象。如果没有与之关联的Document对象,则返回null

  • Node.isConnected,检测该节点是否已经连接到一个上下文对象,可用来判断一个节点是否已插入文档中

另外,还有一组与之类似的新属性,是只考虑文档中的HTMLElment类型节点,忽略Text节点。Node.children,Node.childElementCount,Node.firstElementChild,Node.lastElementChild,Node.parentElement,Node.nextElementSibling,Node.previousElementSibling

Node 类型属性

Node 方法

  • Node.appendChild(child),将指定节点作为最后一个子节点添加到当前节点。不能跨文档插入,只能将某个节点插入到同一文档的其他位置

  • Node.insertBefore(newNode,referenceNode),在参考节点之前插入一个子节点。

    • 如果要插入的节点是对文档中现有节点的引用,那么insertBefore()会将其从当前位置移动到新的位置。这意味着,一个节点不能同时位于文档的两个位置
    • 如果插入节点在选用文档中,可使用Node.cloneNode()复制该节点,但需要注意,该节点 副本不会自动同原始节点保持同步
    • 如果引用节点null,则指定节点添加到父节点末尾。
    • 如果给定的子节点是DocumentFragment,那么其全部内容将被移动到父节点的子节点列表中
  • Node.removeChild(child),移除当前节点的指定子节点,并返回移除的节点。如果参数引用了 DOM 树上现有的节点,则节点从当前位置分离,并添加到新位置

  • Node.repalceChild(newChild,oldChild),用指定节点替换当前节点的一个子节点。并返回被替换掉的节点。

  • Node.cloneNode(deep),克隆一个节点,参数deep可选,是否参数深度克隆,为true,则该节点的所有后代节点也会被克隆,false,则只会克隆该节点本身。

    • 克隆一个元素节点会拷贝它所有的属性以及属性值。所有属性上绑定的事件会被拷贝(例如node.onclick="alert(123)")。但是不会拷贝使用addEvntListener()方法或者`node.onclick=”fn”这种动态绑定的事件
    • 如果元素节点设置了id属性,并且克隆节点要插入相同的文档中,那么应该更改克隆节点的id属性,以保持唯一性。name属性可能也需要进行修改。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <body>
    <div id="box">
    <p onclick="alert(123)">nihao</p>
    <p>天天向上</p>
    </div>

    <script>
    function sayHello() {
    alert("hello");
    }
    var box = document.getElementById("box");
    var p2 = box.lastElementChild;
    p2.onclick = sayHello;
    let clone = box.cloneNode();
    clone.setAttribute("id", "clone");
    let deepClone = box.cloneNode(true);
    deepClone.setAttribute("id", "deepClone");

    console.log(
    "clone: %o, deepClone: %o",
    clone.childNodes,
    deepClone.childNodes
    );
    box.parentNode.appendChild(clone);
    box.parentNode.appendChild(deepClone);
    </script>
    </body>
  • Node.getRootNode(),返回上下文对象的根节点

  • Node.hasChildNodes(),该节点是否包含子节点

  • Node.contains(otherNode),传入节点是否为该节点的后代节点.**如果插入节点是该节点本身,则也返回 ture. (例如document.body.contains(document.body),返回 true) **

  • Node.isEqualNode(),判断两个节点是否相同。两节点类型相同,且属性、属性值,节点值相同,则返回 true。

Documnet 类型

JavaScript 通过 Document 类型表示文档,它是HTMLDocument的一个实例。在浏览器中,document对象表示整个 HTML 页面,是 window 对象的一个属性,因此可以将其作为全局对象来访问。通过该document对象,不仅可以取得与页面相关的信息,而且还能操作页面的外观以及其底层结构。

文档子元素

  • Document.documentElement,返回当前文档的直接子节点,在 HTML 文档中,指向 HTML 页面的<html>元素
  • Document.body,指向<body>元素

文档信息

  • Document.doctype,返回文档类型定义
  • Document.characterSet,返回当前文档的字符编码
  • Document.title,获取或设置文档的标题
  • Document.cookie,返回一个使用分号分隔的 cookie 列表,或设置一个 cookie
  • Document.location,返回当前文档的 Location对象。

查找元素

  • getElementById(),返回一个Element元素
  • getElementTagName(),返回元素的 HTML 集合HTMLCollection
  • querySelector()m 根据 css 选择器匹配,返回匹配的第一个Element元素
  • querySelectorAll(), 返回一个节点集合NodeList
HTMLCollection 和 NodeList

NodeList是一个节点的集合,由Node.chidNodesdocumet.querySelectorAll()返回的。有item(),entries(),keys(),values()方法

  • 一些情况下,NodeList是一个实时集合,例如Node.childNodes是实时的
  • 在其他情况下,NodeList是一个静态集合,例如,querySelectorAll()返回的是一个静态NodeList.

HTMLCollection是一个包含了 html 元素的集合,由getElementByTagName()返回的,它是即时更新的(live),当其所包含的文档结构发生改变时,它会自动更新。有item()namedItem()方法

特殊结合

  • Document.all,返回一个以文档节点为根节点的 HTMLAllCollection集合
  • Document.forms,返回当前 文档中所有表单元素<form>HTMLCollection列表
  • Document.images,返回当前文档中所有图片元素<img>HTMLCollection列表
  • Document.links,返回当前文档中所有超链接元素<a>HTMLCollection列表

Element 类型

Element 类型通常用于表现 THML 或 XML 元素,这个接口描述了所有相同类型元素所具有的方法和属性。一些接口继承自Element并增加了一些额外功能,例如,HTMLElement接口是所有 HTML 元素的基本接口。

元素特性信息
  • Element.id,该元素的 id 属性值
  • Element.tagName,该元素标签名,同Node.nodeName值相同.注意,标签名以全部大写表示
  • Element.className,该元素的 class 属性的值
  • Element.classList,该元素包含的 calss 属性,是一个DOMTokenList
  • Element.attributes,与该元素相关的所有属性的集合NamedNodeMap
  • Element.innerHTML,元素的内容
获取/设置特性
  • getAttribute(name),返回元素上一个指定的属性值,如果不存在,返回null
    • style特性,其属性值和通过getAttribute()返回的值不同,前者返回一个对象CSSStyleDeclaration,后者返回 style 特性值中包含 CSS 文本
    • onclicke特性,属性值返回一个 JavaScript 函数 ,getAttribute()返回相应代码的字符串
  • setAttribute(name, value),设置元素上的某个属性值,如果属性已存在,则更新该值。
  • removeAttribute(name),从元素 中删除指定属性。

classList 属性

元素的classList属性是一个DOMTokenList集合,此类型定义了以下方法:

  • add(value),将指定字符串值添加到列表,如果已存在,则忽略
  • remove(value),从列表删除给定的字符串
  • toggle(value),如果列表中已存在给定的值,删除它。如果不存在,添加它。
  • contains(value),列表中是否存在给定的值
attrubutes 属性
  • Element.attributes,返回与该元素相关的所有属性的实时集合NamedNodeMap
  • NamedNodeMap接口表示属性节点Attr对象的集合,它也是即时的(live),如果它内部包含的对象发生改变,该对象会自动更新。
元素尺寸/位置信息
  • Element.clientHeight,Element.clientWidth,元素内部像素高度/宽度(包含内边距,但不包括滚动条,边框和外边距)
  • Element.offsetHeight,Element.offsetWidth,元素像素高度/宽度,包含元素的内边距,边框,和滚动条(chrome 17px)
  • Element.scrollHeight,Element.scrollWidth,元素的滚动视图高度/宽度,包括由于溢出导致的不可见内容。
    • 在没有滚动条情况下,同 clientHeight,clientWidth值相同
    • scrollHeight也包括::before::after伪元素
  • Element.scrollTop,Element.scrollLeft,元素纵向/横向滚动条位置(即超出可视区域的内容大写)纵向滚动条最底层滚动条位置:scrollTop = scrollHeight - clientHeight
创建元素
  • document.createElement(tagName),创建一个由标签名称指定的 HTML 元素
  • document.createTextNode(),创建一个新的文本节点
  • document.createAttribute(),创建并返回一个新的属性节点

insertAdjacentHTML()

element.insertAdjacentHTML(position,text),将指定的文本,解析为 Element 元素,并将结果节点插入到 DOM 树种的给定位置。参数position表示插入内容相对于元素的位置。

  • "beforbegin",插入到元素自身的前面
  • "afterbegin",插入到元素内部的第一个子节点之前
  • "beforeend",插入到元素内部的最后一个子节点之后
  • "afterend",元素自身的后面
1
2
3
4
5
6
7
8
9
10
<!-- beforebegin -->
<div>
<!-- afterbegin -->
<p>...</p>
<p>...</p>
<p>...</p>
<!-- beforeend -->
</div>
<!-- afterend -->

Text 类型

文本节点由 Text 类型表示,可以包含转义后的 HTML 字符,但不能包含 HTML 代码。

操作文本节点

  • appendData(text),添加文本到节点末尾
  • deleteData(offset, count),从 offset 指定位置开始删除 count 个字符
  • insertData(offset,text),在 offset 位置插入文本
  • replaceDate(offset,count,text),用 text 替换从 offset 指定位置开始到offset+count为止处的文本
  • splitText(offset),从 offset 处将文本分成 2 个文本节点
  • substringData(offset,count),提取从 offset 位置到offset + count为止处的字符串
  • normalize(),规范文本节点,在包含 2 个或多个文本节点的父元素上调用,会将所有文本节点合并成一个节点

DocumentFragment 类型

文档片段是一种“轻量级”的文档,可以包含、控制节点,但不会像完整的文档那些占用额外资源。虽然不能将文档片段直接添加到文档,但可以将它当作一个“仓库”开使用,在里面保存将来可能要添加到文档的节点。

  • 文档片段继承了Node所有方法
  • 在 将文档片段添加文档时,实际上只会将文档片段所有的子节点添加到文档相应的位置,此时文档片段中的所有子节点都被删除。

Attr 类型

元素的特性在 DOM 中以 Attr 类型表示。

  • 元素的attributes属性中节点,即使特性节点
  • 尽管其也是节点,但特性却不认为是 DOM 文档树的部分。

方便的表格操作

为了方便构建表格,HTMLDOM 还为<table>,<tbody>,<tr>元素提供了一些特殊的属性和方法.

table 元素

  • caption,对<caption>元素的指针
  • tFoot,对<tfoot>元素的指针
  • tHead,对<thead>元素是指针
  • tBodies,<tbody>元素的 HTMLCollection
  • rows,表格所有行的 HTMLCOllection
  • createTHead(),deleteTHead(),创建/删除<thead>元素
  • createTFoot,deleteTFoot(),创建/删除<tfoot>元素
  • insetRow(pos),像 rows 集合中的指定位置插入一行
  • deleteRow(pos),删除指定位置的行

    tbody 元素

  • rows<tbody>元素 中所有行的 HTMLCollection
  • insertRow(pos),deleteRow(pos),在<tbody>元素中,向 rows 集合中插入/删除指定 位置的一行

tr 元素

  • cells<tr>元素单元格的 HTMLCollection
  • insertCell(pos)deleteCell(),向 cells 集合中,插入/删除指定的一个单元格

DOM 对性能的影响

  • NodeList对象是“动态的”,这意味中每次访问NodeList对象,都会运行一次基于文档的查询,因此,要尽量减少 DOM 操作
  • 文档中每一次的添加(appendChild())或插入(insertBefore())节点,都会触发 DOM 树的重新渲染。可先在文档片段(document fragment)中处理好后,在一次性的插入到文档中,这种操作仅发生一次重新渲染。