一、什么是 HTML DOM?
DOM 是一项 W3C (World Wide Web Consortium) 标准。DOM 定义了访问文档的标准:“W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问、更新文档的内容、结构和样式。” 而HTML DOM 是 HTML 的标准对象模型和编程接口。通过 HTML DOM,JavaScript 能够获取、更改、添加或删除 HTML 文档的所有元素。
对于DOM集合接口,一般的规定是:
node.childNodes 结果返回类型是 NodeList。
node(document或者其他不同节点).getElementsByXXX 结果返回类型是HTMLCollection。
node.children 结果返回类型是 HTMLCollection。
二、NodeList与HTMLCollection的区别。
HTMLCollection是 HTML 元素的集合。
NodeList 是文档节点的集合。
HTMLCollection 和 NodeList 对象都是类数组的对象列表(集合)。
都有定义列表(集合)中项目数的 length 属性。
都可以通过索引 (0, 1, 2, 3, 4, ...) 像数组那样访问每个项目。
可以通过它们的名称、id 或索引号,问 HTMLCollection 项目。
访问 NodeList 项目,只能通过它们的索引号。
只有 NodeList 对象能包含属性节点和文本节点。
1.NodeList类型
NodeList对象是一个节点的集合,是由Node.childNodes and the querySelectorAll方法返回的.NodeList 中的元素可通过索引号进行访问。
代码举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>遍历元素节点NodeList类型</title>
</head>
<body>
<ul>
<li>返回1号</li>
<li>返回2号</li>
<li>返回3号</li>
<li>返回4号</li>
<li>返回5号</li>
</ul>
</body>
<script>
var ul = document.querySelector("ul");
console.log(ul);
// 子节点
console.log(ul.childNodes);
console.log(ul.childNodes.length);
console.log(ul.childNodes[2]);
// js 节点有11种类型,但是与html相关的只有6个
// 1: 元素
// 2: 属性
// 3: 文本
// 6: 注释
// 9: 文档, document
// 11: 文档片断
console.log(ul.childNodes[0]);
console.log(ul.childNodes[0].nodeType); //查看节点类型
console.log(ul.childNodes[1].nodeValue); //查看节点值
console.log(ul.childNodes[1].nodeName); //查看节点名称
// 最后一个
console.log(ul.childNodes[ul.childNodes.length - 1]);
console.log(ul.childNodes[ul.childNodes.length - 2].nodeName);
// 遍历
var eles = [];
ul.childNodes.forEach(function (item) {
// 只返回类型为1的元素节点
if (item.nodeType === 1) this.push(item);
}, eles);
console.log(eles);
//获取第一个子节点
console.log(ul.firstChild);
// cl(ul.childNodes[0]);
console.log(ul.childNodes[ul.childNodes.length - 1]);
// 最后一个子节点
console.log(ul.lastChild);
// 前一个兄弟节点
console.log(ul.lastChild.previousSibling);
// 后一个兄弟节点
console.log(ul.firstChild.nextSibling);
</script>
</html>
输出效果:
2.HTMLCollection类型
HTMLCollection 对象是类数组的 HTML 元素列表(集合)。
HTMLCollection特点:
键名:是从0开始的正整数。
有一个length属性,表示数量。
HTMLCollection 看起来像数组,但并不是数组。我们可以遍历列表并通过数字引用元素(就像数组那样)。但是不能对 HTMLCollection使用数组方法,比如 valueOf()、pop()、push() 或 join()。
代码举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>遍历dom元素HTMLCollection</title>
</head>
<body>
<ul id="list">
<li class="item" name="first">我是第1个</li>
<li class="item">我是第2个</li>
<li class="item">我是第3个</li>
<li class="item active">我是第4个</li>
<li class="item">我是第5个</li>
</ul>
</body>
</html>
<script>
// 1. 标签
var lis = document.getElementsByTagName("li");
console.log(lis);
// HTMLCollection:类数组
console.log(lis[2]);
console.log(lis.item(2));
console.log(lis.length);
// 2. id
var ul = document.getElementById("list");
console.log(ul);
// 3. class
var lis = document.getElementsByClassName("item");
var lis = document.getElementsByClassName("item active");
console.log(lis.item(0));
// 4. name
var first = document.getElementsByName("first");
console.log(first[0]);
// 5. css选择器
var ul = document.querySelector("#list");
console.log(ul);
var li = document.querySelector(".item");
console.log(li);
var lis = document.querySelectorAll(".item");
console.log(lis);
var lis = document.querySelectorAll("#list > li:nth-of-type(-n+3");
lis.forEach(function (item) {
item.style.color = "red";
});
</script>
输出效果:
3.node.children 结果返回类型也是 HTMLCollection。
代码举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>遍历元素节点返回类型也是 HTMLCollection</title>
</head>
<body>
<ul>
<li>我是第1个元素节点</li>
<li>我是第2个元素节点</li>
<li>我是第3个元素节点</li>
<li>我是第4个元素节点</li>
<li>我是第5个元素节点</li>
</ul>
</body>
<script>
var ul = document.querySelector("ul");
// children
// childNodes: 返回所有节点,包括元素,文本...
console.log(ul.childNodes);
// children: 只返回元素
console.log(ul.children);
console.log(ul.children.length);
console.log(ul.childElementCount);
// 第一个元素
console.log(ul.firstElementChild);
// 最后一个
console.log(ul.lastElementChild);
// 任何一个
console.log(ul.children[2]);
// 前一个兄弟
console.log(ul.children[2].previousElementSibling);
//后一个兄弟
console.log(ul.children[3].nextElementSibling);
// HTMLCollection没有forEach
console.log("-----------");
for (var i = 0; i < ul.childElementCount; i++) {
console.log(ul.children.item(i));
}
</script>
</html>
输出效果:
三、DOM事件的添加方式
HTML DOM 允许 JavaScript 对 HTML 事件作出反应,即:当用户点击某个 HTML 元素时,JavaScript 能够在事件发生时执行。
DOM事件的添加方式:
1. 给html元素绑定事件属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>1. 给html元素绑定事件属性</title>
</head>
<body>
<button onclick="var text=this.innerText;alert(text);">按钮1</button>
<button onclick="show(this)">按钮2</button>
</body>
<script>
function show(ele) {
var text = ele.innerText;
alert(text);
}
</script>
</html>
输出效果:
2.给html元素添加属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2.给html元素添加属性</title>
</head>
<body>
<button onclick="var text=this.innerText;alert(text);">按钮3</button>
</body>
<script>
var btn3 = document.querySelector("button");
btn3.onclick = function () {
alert(this.nodeName);
};
</script>
</html>
输出效果:
3.监听器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3.监听器方式</title>
</head>
<body>
<button onclick="var text=this.innerText;alert(text);">按钮4</button>
</body>
<script>
// 3. 监听器
var btn4 = document.querySelector("button");
// btn4.addEventListener(事件类型, 事件回调函数, 传递机制)
btn4.addEventListener(
"click",
function () {
alert(this.innerText);
},
// false: 冒泡阶段触发
false
);
</script>
</html>
输出效果:
4.事件派发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4.事件派发</title>
</head>
<body>
<button onclick="var text=this.innerText;alert(text);">按钮5</button>
</body>
<script>
var btn5 = document.querySelector("button");
btn5.addEventListener(
"click",
function () {
alert(this.innerText);
},
false
);
</script>
</html>
输出效果:
四、事件传递与事件委托(事件委托也叫做事件代理)
1.事件传递
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件传递与事件委托/代理</title>
</head>
<body>
<div class="first">
<div class="second">
<div class="three">事件传递</div>
</div>
</div>
</body>
<script>
var first = document.querySelector(".first");
var second = document.querySelector(".second");
var three = document.querySelector(".three");
// true: 捕获阶段触发事件
first.addEventListener(
"click",
function (ev) {
console.log(
"捕获阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
true
);
second.addEventListener(
"click",
function (ev) {
console.log(
"捕获阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
true
);
three.addEventListener(
"click",
function (ev) {
console.log(
"捕获阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
true
);
</script> -->
</html>
输出效果:
2.事件委托
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件传递与事件委托/代理</title>
</head>
<body>
<div class="first">
<div class="second">
<div class="three">事件委托</div>
</div>
</div>
</body>
<script>
var first = document.querySelector(".first");
var second = document.querySelector(".second");
var three = document.querySelector(".three");
// false: 冒泡阶段触发事件
first.addEventListener(
"click",
function (ev) {
cl(
"冒泡阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
false
);
second.addEventListener(
"click",
function (ev) {
cl(
"冒泡阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
false
);
three.addEventListener(
"click",
function (ev) {
cl(
"冒泡阶段:" + "触发: " + ev.target.classList.item(0),
"绑定:" + ev.currentTarget.classList.item(0)
);
},
false
);
</script>
<!-- 冒泡实现事件的委托/代理 -->
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
</ul>
<script>
document.querySelector("ul").addEventListener("click", function (ev) {
console.log("当前触发事件的元素是:", ev.target);
});
</script>
</html>
输出效果:
五、总结
1.querySelectorAll 返回的是 NodeList,但是实际上是元素集合,并且是静态的。其他接口返回的HTMLCollection和NodeList都是动态的,即取得的结果会随着相应元素的增减而增减。
2.事件传递是由外向内触发代码。
3.事件委托是由内向外触发代码。