一、DOM的概念
DOM是Document Object Model的缩写,意思是『文档对象模型』——将HTML文档抽象成模型,再封装成对象方便用程序操作。
这是一种非常常用的编程思想:将现实世界的事物抽象成模型,这样就非常容易使用对象来量化的描述现实事物,从而把生活中的问题转化成一个程序问题,最终实现用应用软件协助解决现实问题。而在这其中『模型』就是那个连通现实世界和代码世界的桥梁。
二、DOM树的概念
浏览器把HTML文档从服务器上下载下来之后就开始按照『从上到下』的顺序『读取HTML标签』。每一个标签都会被封装成一个『对象』。
而第一个读取到的肯定是根标签html,然后是它的子标签head,再然后是head标签里的子标签……所以从html标签开始,整个文档中的所有标签都会根据它们之间的『父子关系』被放到一个『树形结构』的对象中。
这个包含了所有标签对象的整个树形结构对象就是JavaScript中的一个可以直接使用的内置对象:document。
例如,下面的标签结构:
会被解析为:
三、各个组成部分的类型
整个文档中的一切都可以看做Node。各个具体组成部分的具体类型可以看做Node类型的子类。
其实严格来说,JavaScript并不支持真正意义上的『继承』,这里我们借用Java中的『继承』概念,从逻辑上来帮助我们理解各个类型之间的关系。
组成部分 | 节点类型 | 具体类型 |
---|---|---|
整个文档 | 文档节点 | Document |
HTML标签 | 元素节点 | Element |
HTML标签内的文本 | 文本节点 | Text |
HTML标签内的属性 | 属性节点 | Attr |
父子关系
先辈后代关系
四、DOM操作
由于实际开发时基本上都是使用JavaScript的各种框架来操作,而框架中的操作方式和我们现在看到的原生操作完全不同,所以下面罗列的API仅供参考,不做要求。
① 在整个文档范围内查询元素节点
功能 | API | 返回值 |
---|---|---|
根据id值查询 | document.getElementById(“id值”) | 一个具体的元素节 |
根据标签名查询 | document.getElementsByTagName(“标签名”) | 元素节点数组 |
根据name属性值查询 | document.getElementsByName(“name值”) | 元素节点数组 |
根据类名查询 | document.getElementsByClassName("类名") | 元素节点数组 |
② 在具体元素节点范围内查找子节点
功能 | API | 返回值 |
---|---|---|
查找子标签 | element.children | 返回子标签数组 |
查找第一个子标签 | element.firstElementChild | 标签对象 |
查找最后一个子标签 | element.lastElementChild | 节点对象 |
③ 查找指定元素节点的父节点
功能 | API | 返回值 |
---|---|---|
查找指定元素节点的父标签 | element.parentElement | 标签对象 |
④ 查找指定元素节点的兄弟节点
功能 | API | 返回值 |
---|---|---|
查找前一个兄弟标签 | node.previousElementSibling | 标签对象 |
查找后一个兄弟标签 | node.nextElementSibling | 标签对象 |
⑤ DOM操作之查找元素案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM之查询</title>
</head>
<body>
<div id="div01">
<input type="text" id="username" name="aaa"/>
<input type="text" id="password" name="aaa"/>
<input type="text" id="email"/>
<input type="text" id="address"/>
</div>
<input type="text"/><br>
<input type="button" value="整个文档搜索按钮" id="btn01"/>
<input type="button" value="具体元素子级搜索按钮" id="btn02"/>
<input type="button" value="子级找父级搜索按钮" id="btn03"/>
<input type="button" value="兄弟搜索按钮" id="btn04"/>
<script>
document.getElementById("btn01").onclick=function () {
//根据id属性值获得元素对象
var elementById = document.getElementById("username");
console.log(elementById);
//根据标签名称获得元素对象数组
var inputs = document.getElementsByTagName("input");
console.log(inputs.length);
for (var i = 0; i < inputs.length; i++) {
console.log(inputs[i]);
}
//根据name属性值获得元素对象数组
var elementsByName = document.getElementsByName("aaa");
console.log(elementsByName.length);
for (var i = 0; i < elementsByName.length; i++) {
console.log(elementsByName[i]);
}
}
document.getElementById("btn02").onclick=function () {
//从div内搜索
var div01 = document.getElementById("div01");
//div01中的所有子节点元素数组
var children = div01.children;
console.log(children.length);
for (var i = 0; i < children.length; i++) {
console.log(children[i]);
}
//第一个子节点元素
var firstElementChild = div01.firstElementChild;
console.log(firstElementChild);
//最后一个子节点元素
var lastElementChild = div01.lastElementChild;
console.log(lastElementChild);
}
document.getElementById("btn03").onclick=function () {
var elementById = document.getElementById("password");
//父级节点元素
var parentElement = elementById.parentElement;
console.log(parentElement)
}
document.getElementById("btn04").onclick=function () {
var elementById = document.getElementById("password");
//前一个兄弟
var previousElementSibling = elementById.previousElementSibling;
console.log(previousElementSibling)
//后一个兄弟
var nextElementSibling = elementById.nextElementSibling;
console.log(nextElementSibling)
}
</script>
</body>
</html>
⑥ 属性操作
需求 | 操作方式 |
---|---|
读取属性值 | 元素对象.属性名 |
修改属性值 | 元素对象.属性名=新的属性值 |
⑦ 标签体的操作
需求 | 操作方式 |
---|---|
获取或者设置标签体的文本内容 | element.innerText |
获取或者设置标签体的内容 | element.innerHTML |
⑧ DOM操作之属性标签体操作案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>操作标签的属性和文本</title>
</head>
<body>
<input type="text" id="username" name="username" />
<div id="d1">
<h1>你好世界</h1>
</div>
<script>
//目标: 获取id为username的输入框的value
//1. 找到要操作的标签
var ipt = document.getElementById("username");
//2. 设置标签的value属性值
ipt.value = "张三"
//3. 获取标签的value属性的值
var value = ipt.value;
console.log(value)
//获取id为d1的div中的文本内容
//获取标签的文本: element.innerText,获取文本的时候会将左右两端的空格去掉
var innerText = document.getElementById("d1").innerText;
console.log(innerText)
//获取标签体的内容: element.innerHTML,获取标签体的内容
var innerHTML = document.getElementById("d1").innerHTML;
console.log(innerHTML)
//设置标签体的内容:建议使用innerHTML,如果是使用innerText的话它会将标签当做普通文本处理
document.getElementById("d1").innerHTML = "<h1>hello world</h1>"
</script>
</body>
</html>
⑨ DOM增删改操作
API | 功能 |
---|---|
document.createElement(“标签名”) | 创建元素节点并返回,但不会自动添加到文档中 |
document.createTextNode(“文本值”) | 创建文本节点并返回,但不会自动添加到文档中 |
element.appendChild(ele) | 将ele添加到element所有子节点后面 |
parentEle.insertBefore(newEle,targetEle) | 将newEle插入到targetEle前面 |
parentEle.replaceChild(newEle, oldEle) | 用新节点替换原有的旧子节点 |
element.remove() | 删除某个标签 |
⑩DOM操作之增删改案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>创建和删除标签</title>
</head>
<body>
<ul id="city">
<li id="bj">北京</li>
<li id="sh">上海</li>
<li id="sz">深圳</li>
<li id="gz">广州</li>
</ul>
<script>
//目标1: 在城市列表的最后添加一个子标签 <li id="cs">长沙</li>
//1. 创建一个li标签 <li></li>
var liElement = document.createElement("li");
//2. 给创建的li标签设置id属性和文本 <li id="cs">长沙</li>
liElement.id = "cs"
liElement.innerText = "长沙"
//3. 将创建的li标签添加到城市列表中(ul)
var cityUl = document.getElementById("city");
//父.appendChild(子)将子标签添加到父标签的最后面
//cityUl.appendChild(liElement)
//目标2:在城市列表的深圳之前添加一个子标签 <li id="cs">长沙</li>
//获取到深圳这个标签
var szElement = document.getElementById("sz");
//父.insertBefore(新标签,参照标签)
//cityUl.insertBefore(liElement,szElement)
//目标3: 在城市列表中添加一个子标签替换深圳 <li id="cs">长沙</li>
//父.replaceChild(新标签,被替换的标签)
//cityUl.replaceChild(liElement,szElement)
//目标4: 在城市列表中删除深圳
//szElement.remove()
//目标5: 清除城市列表中的所有城市,保留城市列表标签ul
cityUl.innerHTML = ""
</script>
</body>
</html>