JS HTML DOM
HTML DOM (文档对象模型)
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
HTML DOM 定义了用于 HTML 的一系列标准的对象,以及访问和处理 HTML 文档的标准方法。通过 DOM,你可以访问所有的 HTML 元素,连同它们所包含的文本和属性。
HTML DOM 独立于平台和编程语言。它可被任何编程语言诸如 Java、JavaScript 和 VBScript 使用。
HTML DOM 模型被构造为对象的树:

查找 HTML 元素
通常,通过 JavaScript,您需要操作 HTML 元素。
为了做到这件事情,您必须首先找到该元素。有三种方法来做这件事:
- 通过 id 找到 HTML 元素
document.getElementById("myBtn") - 通过标签名找到 HTML 元素
- 通过类名找到 HTML 元素
传统写法
1 | // 返回ID为'test'的节点: |
第二种方法是使用 querySelector() 和querySelectorAll(),需要了解 selector 语法,然后使用条件来获取节点,更加方便:
1 | // 通过 querySelector 获取ID为 q1 的节点: |
注意:低版本的 IE<8不支持querySelector 和 querySelectorAll。IE8 仅有限支持。
若非特殊情况,我们建议首选:querySelector() 和 querySelectorAll() 它们是最灵活、最强大的方法,因为它们可以使用任何 CSS 选择器。 querySelectorAll() 返回的 NodeList 通常比 getElementsByTagName() 和 getElementsByClassName() 返回的 HTMLCollection 更易于使用。 它们是现代 Web 开发的标准做法。
次选:getElementById() 如果你需要通过 id 获取单个元素,并且需要极致的性能,那么 getElementById() 仍然是一个不错的选择。
尽量避免:getElementsByTagName() 和 getElementsByClassName() 除非你 specifically 需要“活”的 HTMLCollection,或者你需要兼容非常旧的浏览器(IE8 及更早版本),否则通常应该优先使用 querySelectorAll()。
getElementById() 返回对拥有指定 id 的第一个对象的引用。
getElementsByName() 返回带有指定名称的对象集合。
getElementsByTagName() 返回带有指定标签名的对象集合。
document.getElementsByClassName
document.querySelector() 方法返回文档中与指定选择器或选择器组匹配的第一个 html 元素Element。 如果找不到匹配项,则返回 null。
查找第一个匹配 class 属性的 html 元素 这个例子中,会返回当前文档中第一个类名为 “myclass” 的元素:
1 | document.querySelector(".myclass"); |
获取匹配列表
1 | var matches = document.querySelectorAll("p"); |
此示例返回文档中所有<div>元素的列表,其中
class 包含 “note” 或 “alert”:
1 | var matches = document.querySelectorAll("div.note, div.alert"); |
在这里,我们得到一个 <p> 元素的列表,其直接父元素是一个 class
为 "highlighted" 的div,并且位于
ID 为 "test" 的容器内。
1 | var container = document.querySelector("#test"); |
此示例使用属性选择器返回文档中属性名为"data-src"的iframe元素列表:
1 | var matches = document.querySelectorAll("iframe[data-src]"); |
这里,属性选择器用于返回 ID
为 "userlist" 的列表中包含值为 "1" 的 "data-active" 属性的元素
1 | var container = document.querySelector("#userlist"); |
文档本身是文档节点 所有 HTML 元素是元素节点 所有 HTML 属性是属性节点 HTML
元素内的文本是文本节点 注释是注释节点
HTML DOM Attribute 对象
在 HTML DOM (文档对象模型)中,每个部分都是节点:
1 | <input id="xbb" type="text" value="lalalla"></input> |
1 | var haha = document.getElementById("xbb"); |
创建 HTML 元素并插入
在文档对象模型 (DOM) 中,每个节点都是一个对象。DOM 节点有三个重要的属性,分别是:
- nodeName : 节点的名称
- nodeValue :节点的值
- nodeType :节点的类型
appendChild
有两个办法可以插入新的节点。一个是使用 appendChild,把一个子节点添加到父节点的最后一个子节点。例如:
1 | // 添加新元素,您必须首先创建该元素(元素节点) |
注:如果我们插入的 js 节点已经存在于当前的文档树,因此这个节点首先会从原先的位置删除,再插入到新的位置。
我们在学习了动态创建一个节点然后添加到 DOM 树后,可以实现很多功能。举个例子,下面的代码动态创建了一个<style>节点,然后把它添加到<head>节点的末尾,这样就动态地给文档添加了新的CSS定义:
1 | let d = document.createElement('style'); |
可以在 Chrome 的控制台执行上述代码,观察页面样式的变化。
insertBefore
如果我们要把子节点插入到指定的位置怎么办?可以使用parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前。
删除已有的 HTML 元素
1 | <div id="div1"> |
注意:当你遍历一个父节点的子节点并进行删除操作时,子节点变化时会实时更新。
改变 HTML 内容
改变 HTML 输出流
JavaScript 能够创建动态的 HTML 内容:
在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容。如果您在文档加载后使用该方法,会覆盖整个文档。
修改 HTML 内容的最简单的方法是使用 innerHTML 属性。
改变 HTML 属性
拿到一个 DOM 节点后,我们可以对它进行更新。
可以直接修改节点的文本,方法有两种:
一种是修改 innerHTML 属性,这个方式非常强大,不但可以修改一个DOM节点的文本内容,还可以直接通过 HTML 片段修改 DOM 节点内部的子树:
用 innerHTML 时要注意,是否需要写入HTML。如果写入的字符串是通过网络拿到的,要注意对字符编码来避免XSS攻击。
第二种是修改 innerText 或 textContent 属性,这样可以自动对字符串进行 HTML 编码,保证无法设置任何HTML标签:
1 | // 获取<p id="p-id">...</p> |
两者的区别在于读取属性时,innerText 不返回隐藏元素的文本,而 textContent 返回所有文本。另外注意IE<9不支持 textContent。
改变 HTML 样式
修改 CSS 也是经常需要的操作。DOM 节点的 style 属性对应所有的CSS,可以直接获取或设置。因为CSS允许 font-size 这样的名称,但它并非JavaScript 有效的属性名,所以需要在JavaScript中改写为驼峰式命名 fontSize:
1 | // 获取<p id="p-id">...</p> |
HTML DOM 事件
HTML 事件的例子:
- 当用户点击鼠标时
- 当网页已加载时
- 当图像已加载时
- 当鼠标移动到元素上时
- 当输入字段被改变时
- 当提交 HTML 表单时
- 当用户触发按键时
使用 HTML DOM 来分配事件
HTML DOM 允许您使用 JavaScript 来向 HTML 元素分配事件:
1 |
|
除了
1 | document.getElementById("myBtn").onclick = function () { |
我们可用写在行内,但不推荐:<button onclick="displayDate()">点我</button>。
HTML DOM EventListener
addEventListener() 方法
addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。
你可以向一个元素添加多个事件句柄。
你可以向同个元素添加多个同类型的事件句柄,如:两个 “click” 事件。
你可以向任何 DOM 对象添加事件监听,不仅仅是 HTML 元素。如: window 对象。
当你使用 addEventListener() 方法时, JavaScript 从 HTML 标记中分离开来,可读性更强, 在没有控制 HTML 标记时也可以添加事件监听
语法
1 | element.addEventListener(event, function, useCapture); |
第一个参数是事件的类型 (如 “click” 或 “mousedown”).
第二个参数是事件触发后调用的函数。
第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。
注意:不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
事件冒泡或事件捕获?
事件传递有两种方式:冒泡与捕获。
事件传递定义了元素事件触发的顺序。 如果你将 <p> 元素插入到 <div> 元素中,用户点击 <p> 元素, 哪个元素的 “click” 事件先被触发呢?
在冒泡中,内部元素的事件会先被触发,然后再触发外部元素,即: <p> 元素的点击事件先触发,然后会触发 <div> 元素的点击事件。
在捕获中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <div> 元素的点击事件先触发 ,然后再触发 <p> 元素的点击事件。
默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。
removeEventListener() 方法
removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄: