JS 入门章节目录
第九章:HTML DOM
文章の目录
firstChild 属性 和 firstElementChild 属性
lastChild 属性和 lastElementChild 属性
nextSibling 属性和 nextElementSibling 属性
previousSibling 属性 和 previousElementSibling 属性
onmousedown,onmouseup 以及 onclick 事件
onmouseenter 和 onmouseleave 事件
onkeydown,onkeyup 以及 onkeypress
正文
通过 HTML DOM,JavaScript 能够访问和改变 HTML 文档的所有元素。
HTML DOM 简介
什么是 DOM?
DOM 是一项 W3C(World Wide Web Consortium)标准。
DOM 定义了访问文档的标准:“W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问、更新文档的内容、结构和样式。”
W3C DOM 标准被分为 3 个不同的部分:
- Core DOM —— 所有文档类型的标准模型
- XML DOM —— XML 文档的标准模型
- HTML DOM —— HTML 文档的标准模型
什么是 HTML DOM?
HTML DOM 是 HTML 的标准对象模型和编程接口。它定义了:
- 作为对象的 HTML 元素
- 所有 HTML 元素的属性
- 访问所有 HTML 元素的方法
- 所有 HTML 元素的事件
换言之:HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准。
HTML DOM 模型 和 DOM 树
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
HTML DOM 模型被结构化为对象树。
对象的 HTML DOM 树:

通过这个对象模型,JavaScript 获得创建动态 HTML 的所有力量:
- JavaScript 能改变页面中的所有 HTML 元素
- JavaScript 能改变页面中的所有 HTML 属性
- JavaScript 能改变页面中的所有 CSS 样式
- JavaScript 能删除已有的 HTML 元素和属性
- JavaScript 能添加新的 HTML 元素和属性
- JavaScript 能对页面中所有已有的 HTML 事件作出反应
- JavaScript 能在页面中创建新的 HTML 事件
HTML DOM 方法和属性
HTML DOM 方法是您能够(在 HTML 元素上)执行的动作。
HTML DOM 属性是您能够设置或改变的 HTML 元素的值。
HTML DOM 编程界面
HTML DOM 能够通过 JavaScript 进行访问(也可以通过其它编程语言)。
在 HTML DOM 中,所有 HTML 元素都被定义为对象。
编程界面是每个对象的属性和方法。
属性是您能够获取或设置的值。
方法是您能够完成的动作。
HTML DOM 文档对象
HTML DOM 文档对象是您的网页中所有其他对象的拥有者。
HTML DOM Document 对象
文档对象代表您的网页。
如果您希望访问 HTML 页面中的任何元素,那么您总是从访问 document 对象开始。
查找 HTML 元素
通常,通过 JavaScript,您需要操作 HTML 元素。
为了达成此目的,您需要首先找到这些元素。有好几种完成此任务的 方法:
- 通过 id 查找 HTMl 元素
- 通过标签名查找 HTML 元素
- 通过类名查找 HTML 元素
- 通过元素的名称查找 HTML 元素
通过 id 查找 HTML 元素
HTML DOM 中查找 HTML 元素最简单的方法是使用元素的 id:
var myElement = document.getElementById("");
如果元素被找到,此方法会以对象返回该元素(在 myElement 中)。
如果未找到元素,myElement 将包含 null。
通过标签名查找 HTML 元素
var myElement = document.getElementsByTagName();
getElementsByTagName() 方法返回一个 HTMLCollection 对象。
HTMLCollection 是 HTML 元素的集合。
HTMLCollection 对象类似一个包含 HTML 元素的数组列表。
通过类名查找 HTML 元素
如果需要找到拥有相同类名的所有 HTML 元素,请使用 getElementsByClassName()。
var myElement = document.getElementsByClassName();
getElementsByClassName() 方法返回一个 HTMLCollection 对象。
通过元素的名称查找 HTML 元素
getElementsByName() 方法可返回带有指定名称的对象的集合。
var myElement = document.getElementsByName(name);
// name:必须。元素的名称。
注:
- getElementsByName() 方法返回指定 name 属性的元素的集合。
- 建议使用以上三种方法(id、标签、类)查找 HTML 元素。
改变 HTML 元素
改变 HTML 输出流
在 JavaScript 中,document.write() 可用于直接写入 HTML 输出流。
千万不要在文档(DOM)加载完成之后使用 document.write() 。这么做会覆盖文档。
语法:
document.write(text)
例:
document.write(Date());
改变 HTML 内容
innerHTML
修改 HTML 文档内容最简单的方法是使用 innerHTML 属性。
innerHTML 属性可用于获取或设置(改变) HTML 元素的内容(开始标签和结束标签内的 HTML)。
语法:
element.innerHTML = newHtmlContent
// newHtmlContent 可以为文本,也可以为标签
例:
document.getElementById("").innerHTML = "文本";
document.getElementById("").innerHTML = "<p>标签</p>";
innerText
innerText 属性可用于获取或设置(改变)HTML 元素的文本内容。
语法:
element.innerText = newText;
注:
- 建议使用 innerHtml 属性代替 innerText 属性。
改变 HTML 元素的属性值
通过 HTML DOM 属性改变 HTML 元素属性的值
语法:
element.attribute = newValue
// 改变 HTML 元素的属性值。
例:
document.getElementById("myImg").src = "picture.jpg";
通过 HTML DOM 方法改变 HTML 元素属性的值
语法:
element.setAttribute(attribute,value)
// 改变 HTML 元素的属性值。
// attribute:属性名
// value:属性值
例:
document.getElementById("myImg").setAttribute("src","picture.jpg");
补充:
element.getAttribute(attribute);
// 获取元素的属性
element.removeAttribute(attribute);
// 删除元素指定的属性
改变 HTML 元素的样式
语法:
element.style.property = newStyle
// 改变 HTML 元素的样式
例:
document.getElementById("text").style.color = "red";
HTML DOM 导航
通过 HTML DOM,您能够使用节点关系来导航节点树。
DOM 节点
根据 W3C HTML DOM 标准,HTML 文档中的所有事物都是节点:
- 整个文档是文档节点
- 每个 HTML 元素是元素节点
- HTML 元素内的文本是文本节点
- 每个 HTML 属性是属性节点
- 所有注释是注释节点

有了 HTML DOM,节点树中的所有节点都能通过 JavaScript 访问。
能够创建新节点,还可以修改和删除所有节点。
节点关系
节点树中的节点彼此之间有一定的等级关系。
- 术语(父、子和同胞,parent、child 和 sibling)用于描述这些关系。
- 在节点树中,顶端节点被称为根(根节点)。
- 每个节点都有父节点,除了根(根节点没有父节点)。
- 节点能够拥有一定数量的子。
- 同胞(兄弟或姐妹)指的是拥有相同父的节点。
在节点之间导航
通过 JavaScript,您可以使用以下节点属性在节点之间导航:
- parentNode
- childNodes[nodenumber] / children
- firstChild / firstElementChild
- lastChild / lastElementChild
- nextSibling / nextElementSibling
- previousSibling / previousElementSibling
注:
- 以上所有属性如果找不到指定节点都会返回 null。
- 以上所有属性都是只读的。
parentNode 属性
parentNode 属性返回元素或节点的父节点(以 Node 对象)。
childNodes 属性和 children 属性
childNodes 属性
childNodes 属性返回元素子节点的集合(列表)。
childNodes 属性返回的是 NodeList 对象。
提示:
- childNodes 返回节点:元素节点、文本节点和注释节点
- 元素之间的空白也是文本节点
children 属性
children 属性返回元素的子元素的集合。
children 属性返回 HTMLCollection 对象。
childNodes 和 children 的区别
childNodes 返回子节点(元素节点、文本节点和注释节点)。
children 返回子元素(元素节点,而非文本节点和注释节点)。
firstChild 属性 和 firstElementChild 属性
firstChild 属性
firstChild 属性返回指定节点的首个子节点(以 Node 对象)。
firstChild 属性与 childNodes[0] 相同。
注:
- firstChild 返回第一个子节点:元素节点、文本节点或注释节点
- 元素之间的空白也是文本节点
firstElementChild 属性
firstElementChild 属性返回指定元素的第一个子元素。
firstElementChild 属性返回与 children[0] 相同的值。
firstChild 和 firstElementChild 的区别
firstChild 返回第一个子节点(元素节点、文本节点或注释节点;元素之间的空白也是文本节点)。
firstElementChild 返回第一个子元素(元素节点,而非文本节点和注释节点)。
lastChild 属性和 lastElementChild 属性
lastChild 属性
lastChild 属性返回指定节点的最后一个子节点(以 Node 对象)。
注:
- lastChild 返回最后一个子节点:元素节点、文本节点或注释节点
- 元素之间的空白也是文本节点
lastElementChild 属性
lastElementChild 属性返回元素的最后一个子元素。
lastChild 和 lastElementChild 的区别
lastChild 返回最后一个子节点(元素节点、文本节点或注释节点;元素之间的空白也是文本节点)。
lastElementChild 返回最后一个子元素(元素节点,而非文本节点和注释节点)。
同胞与元素同胞
同胞是拥有相同父节点的节点(在相同的 childNodes 列表中)。
元素同胞是拥有相同父元素的元素(在相同的 children 列表中)。
nextSibling 属性和 nextElementSibling 属性
nextSibling 属性
nextSibling 属性返回同一树级别上的下一个节点(以 Node 对象)。
注:
- nextSibling 返回下一个同胞节点:元素节点、文本节点或注释节点。
- 元素之间的空白也是文本节点。
nextElementSibling 属性
nextElementSibling 属性返回同一树级别中的下一个元素。
nextSibling 和 nextElementSibling 的区别
nextSibling 返回下一个节点(元素节点、文本节点或注释节点;元素之间的空白也是文本节点)。
nextElementSibling 返回下一个元素(元素节点,而非文本节点和注释节点)。
previousSibling 属性 和 previousElementSibling 属性
previousSibling 属性
previousSibling 属性返回同一树级别的上一个节点(以 Node 对象)。
注:
- previousSibling 返回上一个同胞节点:元素节点、文本节点或注释节点。
- 元素之间的空白也是文本节点。
previousElementSibling 属性
previousElementSibling 属性返回同一树级别中的前一个元素。
previousSibling 和 previousElementSibling 的区别
previousSibling 返回上一个节点(元素节点、文本节点或注释节点;元素之间的空白也是文本节点)。
previousElementSibling 返回上一个元素(元素节点,而非文本节点和注释节点)。
实例
实例1:
<body>
<div id="myDiv">
<!-- 注释 -->
<p>段落</p>
</div>
<script>
let myDiv = document.getElementById("myDiv");
console.log(myDiv.childNodes);
console.log(myDiv.children);
</script>
</body>

实例2:
<body>
<div id="myDiv"><!-- 注释 --><p>段落</p></div>
<script>
let myDiv = document.getElementById("myDiv");
console.log(myDiv.childNodes);
console.log(myDiv.children);
</script>
</body>

实例3:
<title>DOM 教程</title>
提问:如何访问文本节点的值?
- DOM 处理中的一种常见错误是认为元素节点中包含文本。
- 上面例子中的元素节点 <title> 不包含文本。
- 它包含了值为“DOM 教程”的文本节点。
// 文本节点的值能够通过节点的 innerHTML 属性进行访问
var myTitle = document.getElementById("demo").innerHTML;
// 访问 innerHTML 属性等同于访问首个子节点的 nodeValue
var myTitle = document.getElementById("demo").firstChild.nodeValue;
// 也可以这样访问第一个子节点
var myTitle = document.getElementById("demo").childNodes[0].nodeValue;
DOM 根节点
有两个特殊属性允许访问完整文档:
- document.body —— 文档的 body
- document.documentElement —— 完整文档
nodeName 属性
nodeName 属性规定节点的名称。
- nodeName 是只读的
- 元素节点的 nodeName 等同于标签名
- 属性节点的 nodeName 是属性名称
- 文本节点的 nodeName 总是 #text
- 文档节点的 nodeName 总是 #document
注:
- nodeName 总是包含 HTML 元素的大写标签名。
nodeValue 属性
nodeValue 属性规定节点的值。
- 元素节点的 nodeValue 是 undefined
- 文本节点的 nodeValue 是文本节点的值
- 属性节点的 nodeValue 是属性值
nodeType 属性
nodeType 属性返回节点的类型。nodeType 是只读的。
重要的 nodeType 属性:
- 1 —— ELEMENT_NODE(元素节点)
- 2 —— ATTRIBUTE_NODE(属性节点)
- 3 —— TEXT_NODE(文本节点)
注:
- Type 2(属性节点) 在 HTML DOM 中已弃用
节点操作
创建和添加节点
如需向 HTML DOM 添加新节点,必须首先创建这个节点,然后将其追加到已有节点。
创建元素、文本节点
语法:
// 创建元素节点
document.createElement(element)
// 创建文本节点
document.createTextNode(text)
添加节点
appendChild() 方法
追加新节点作为父的最后一个子。
语法:
parent.appendChild(child);
insertBefore() 方法
在指定的已有子节点之前插入新的子节点。
语法:
parentNode.insertBefore(newNode, referenceNode)
// newNode:将要插入的节点
// referenceNode:被参照的节点(即要插在该节点之前)
// parentNode:父节点
实例
var para = document.createElement("p");
var text = document.createTextNode("这是一个段落");
para.appendChild(text);
var con = document.getElementById("container");
var reference = document.getElementById("reference");
con.appendChild(para);
// 效果等同于
con.insertBefore(para,reference);
删除节点
removeChild() 方法
removeChild() 方法删除子节点,这意味着我们必须找到父节点才能删除一个节点。
语法:
parent.removeChild(child)
我们可以找到要删除的子节点,并使用其 parentNode 属性找到父节点:
var child = docuemnt.getElementById("");
child.parentNode.removeChild(child);
remove() 方法
语法:
element.remove()
// remove() 方法需要找到被删除的元素,然后对该元素执行 remove() 方法
注:
- remove() 方法在旧浏览器中不起作用,请使用 removeChild() 取而代之。
替换节点
语法:
element.replaceChild(newChild,oldChild)
HTML DOM 事件
HTML DOM 允许 JavaScript 对 HTML 事件作出反应。
对事件作出反应
JavaScript 能够在事件发生时执行。
当“某些事情”在 HTML 元素上发生时,浏览器会生成事件:
- 当用户点击鼠标时
- 当网页加载后
- 当鼠标移至元素上时
- 当输入字段被改变时
- 当用户敲击键盘时
- ...
向 HTML 元素分配事件
HTML 事件属性
如需向 HTML 元素分配事件,您能够使用事件属性(向事件属性添加 JavaScript 代码)。
例:
<button onclick="this.innerHTML = 'Hello!'">点击替换文本</button>
<button onclick="changeText()">点击替换文本</button>
使用 HTML DOM 分配事件
HTML DOM 允许您使用 JavaScript 向 HTML 元素分配事件。
document.getElementById("myBtn").onclick = changeText;
鼠标事件
onmousedown,onmouseup 以及 onclick 事件
onmousedown,onmouseup 以及 onclick 事件构成了完整的鼠标点击事件。
首先当鼠标按钮被点击时,onmousedown 事件被触发;然后当鼠标按钮被释放时,onmouseup 事件被触发;最后,当鼠标点击完成后,onclick 事件被触发。
ondblclick 事件
当用户双击元素时发生此事件。
onmouseover 和 onmouseout 事件
onmouseover 和 onmouseout 事件可用于当用户将鼠标移至 HTML 元素上(或其中的子元素上)或移出时触发某个函数。
onmouseenter 和 onmouseleave 事件
当指针移动到元素上或从元素上移出时,发生此事件
键盘事件
onkeydown,onkeyup 以及 onkeypress
onkeypress:某个键盘按键被按下并松开
onkeydown:某个键盘按键被按下
onkeyup:某个键盘按键被松开
表单事件
onfocus 和 onblur 事件
在元素获得或失去焦点时发生此事件。
onchange 事件
当 form 元素的内容、选择的内容或选中的状态发生改变时,发生此事件。
onchange 事件经常与输入字段验证结合使用。
onsubmit 事件
在表单提交时触发。
窗口事件
onload 和 onunload 事件
当用户进入后及离开页面时,会触发 onload 和 onunload 事件。
onload 事件会在页面加载完成后立即发生。
onunload 事件在用户退出页面时发生(onunload 发生于当用户离开页面(如:关闭浏览器窗口、点击一个链接、提交表单)时发生的事件)。
注:
- onload 事件可用于检测访问者的浏览器类型和浏览器版本,然后基于该信息加载网页的恰当版本。
- onload 和 onunload 事件可用于处理 cookie。
语法:
在 HTML 中(HTML 事件属性):
<body onload="someJavaScriptCode">
</body>
<!-- onload 用于 <body> 元素,在页面完全载入后(包括图片、css文件等等)执行脚本代码。 -->
在 JavaScript 中(使用 HTML DOM 分配事件):
window.onload = function(){ someJavaScriptCode };
onresize
onresize 事件会在窗口被调整大小时发生。
语法:
window.onresize = function(){}
onscroll
onscroll 事件在元素滚动条滚动时触发。
HTML DOM 事件监听程序
addEventListener() 方法
addEventListener() 方法为指定元素指定事件处理程序。
addEventListener() 方法为元素附加事件处理程序而不会覆盖已有的事件处理程序。
您能够向一个元素添加多个事件处理程序。
您能够向一个元素添加多个相同类型的事件处理程序,例如两个“click”事件。
您能够向任何 DOM 对象添加事件处理程序而非仅仅 HTML 元素。
addEventListener() 方法使我们更容易控制事件如何对冒泡作出反应。
当使用 addEventListener() 方法时,JavaScript 与 HTML 标记是分隔的,以达到更佳的可读性;即使在不控制 HMTL 标记时也允许您添加事件监听器。
您能够通过使用 removeEventListener() 方法轻松地删除事件监听器。
语法:
element.addEventListener(event, function, useCapture);
- 第一个参数是事件的类型(比如“click”或“mousedown”)。
- 第二个参数是当事件发生时我们需要调用的函数。
- 第三个参数是布尔值,指定使用事件冒泡还是事件捕获。此参数是可选的。默认值是 false,将使用冒泡传播,如果该值设置为 true,则事件使用捕获传播。
注意:
- 请勿对事件使用“on”前缀;请使用“click”代替“onclick”。
例:
// 向元素添加事件处理程序
element.addEventListener("click", function(){});
// 或
element.addEventListener("click", myFunction);
// 向相同元素添加多个事件处理程序
// addEventListener() 方法允许您向相同元素添加多个事件,同时不覆盖已有事件
myBtn.addEventListener("click", myFunction);
myBtn.addEventListener("click", mySecondFunction);
事件冒泡还是事件捕获?
在 HTML DOM 中有两种事件传播的方法:冒泡和捕获。
事件传播是一种定义当发生事件时元素次序的方法。例如 <div> 元素内有一个 <p>,然后用户点击了这个 <p> 元素,应该首先处理哪个元素“click”事件?
在冒泡中,最内侧元素的事件会首先被处理,然后是更外侧的:首先处理 <p> 元素的点击事件,然后是 <div> 元素的点击事件。
在捕获中,最外侧元素的事件会首先被处理,然后是更内侧的:首先处理 <div> 元素的点击事件,然后是 <p> 元素的点击事件。
在 addEventListener() 方法中,您能够通过使用“useCapture”参数来规定传播类型。
removeEventListener() 方法
removeEventListener() 方法会删除已通过 addEventListener() 方法附加的事件处理程序。
语法:
element.removeEventListener(event, function);
Event 对象
Event 对象
DOM 中的所有事件对象都基于 Event 对象。
因此,所有其他事件对象都可以访问 Event 对象的属性和方法。
Event 对象属性
cancelable
cancelable 事件属性返回一个布尔值,指示事件是否为可取消事件。
如果可以阻止事件默认操作,则该事件是可取消的。
如需取消事件,请使用 preventDefault() 方法。
语法:
event.cancelable
// 返回值:布尔值,指示指定事件是否为可取消事件
// true —— 事件可取消
// false —— 事件不可取消
Event 对象方法
preventDefault()
如果事件是可取消的,则 preventDefault() 方法会取消该事件,这意味着属于该事件的默认操作将不会发生。
注:
- 并非所有活动都可以取消。请使用 cancelable 属性来确定事件是否可取消。
- preventDefault() 方法不会阻止事件通过 DOM 进一步传播。请使用 stopPropagation() 方法来解决。
语法:
event.preventDefault()
实例:
<!-- 防止链接打开 URL -->
<a href="https://www.baidu.com" id="baidu">百度</a>
<script>
document.getElementById("baidu").addEventListener("click", function(event){
event.preventDefault()
})
// 或者
document.getElementById("baidu").onclick = function(event){
event.preventDefault()
}
// 可以直接在函数内部使用 event,而不用将其作为参数传递进去。
</script>
stopPropagation()
防止事件在事件流中进一步传播。
stopPropagation() 方法防止调用相同事件的传播。
传播意味着向上冒泡到父元素或向下捕获到子元素。
语法:
event.stopPropagation()
实例:
<div id="outside" style="width: 200px; height: 200px; border: 1px solid black;">
<div id="inside" style="width: 100px; height: 100px; border: 1px solid black;">
</div>
</div>
<script>
document.getElementById("outside").addEventListener("click", function(){
console.log("outside 被点击了");
});
document.getElementById("inside").addEventListener("click", function(event){
console.log("inside 被点击了");
event.stopPropagation();
});
</script>
HTMLCollection 对象
HTMLCollection 对象是类数组的 HTML 元素列表(集合)。
该集合中的元素可通过索引号进行访问。索引从 0 开始。
getElementsByTagName() 方法返回 HTMLCollection 对象。
HTMLCollection 长度
length 属性定义了 HTMLCollection 中元素的数量。
length 属性在您需要遍历集合中元素时是有用的。
HTMLCollection 并非数组
HTMLCollection 也许看起来像数组,但并非数组。
您能够遍历列表并通过数字引用元素(就像数组那样)。
不过,您无法对 HTMLCollection 使用数组方法,比如 valueOf()、pop() 或 join()。
NodeList 对象
NodeList 对象是从文档中提取的节点列表(集合)。
NodeList 对象与 HTMLCollection 对象几乎相同。
NodeList 中的元素可通过索引号进行访问。索引从 0 开始。
如使用 getElementsByClassName() 方法,某些(老的)浏览器会返回 NodeList 对象而不是 HTMLCollection 对象。
所有浏览器都会为 childNodes 属性返回 NodeList 对象。
NodeList 长度
length 属性定义节点列表中的节点数。
length 属性在您希望遍历节点列表中的节点时很有用。
节点列表不是数组
节点列表看起来像数组,但并不是。
您能够遍历节点列表并像数组那样引用其节点。
不过,您无法对节点列表使用数组方法,比如:valueOf()、push()、pop() 或 join()。
HTMLCollection 与 NodeList 的区别
HTMLCollection 是 HTML 元素的集合。
NodeList 是文档节点的集合。
HTMLCollection 和 NodeList 几乎完全相同。
HTMLCollection 和 NodeList 对象都是类数组的对象列表(集合)。
它们都有定义列表(集合)中项目数的 length 属性。
它们都可以通过索引(0,1,2,3,4,...)像数组那样访问每个项目。
访问 HTMLCollection 项目,可以通过它们的名称、id 或索引号。
访问 NodeList 项目,只能通过它们的索引号。
只有 NodeList 对象能包含属性节点和文本节点。
本文详细介绍了JavaScript如何通过HTMLDOM来访问和修改HTML文档,包括DOM的基本概念、元素的查找、内容和属性的改变、DOM树结构、节点导航以及事件处理。还涵盖了HTMLDOM中的节点关系、事件监听和不同类型的节点集合如HTMLCollection和NodeList。

3041

被折叠的 条评论
为什么被折叠?



