首页 > 编程笔记 > JavaScript笔记
	 阅读:276
	JavaScript DOM操作教程(非常详细)
DOM 是 Document Object Model 的缩写,翻译为文档对象模型,简单来说就是将 HTML 文档抽象成模型,再封装成对象,目的是方便程序操作。
这是一种非常常用的编程思想,将现实世界的事物抽象成模型,这样就很容易使用对象来量化描述现实事物,从而把生活中的问题转化成一个程序问题,最终实现用应用软件来协助解决现实问题。而模型就是连通现实世界和代码世界的桥梁。
DOM 是 W3C(World Wide Web Consortium)制订的一套技术规范,用来描述 JavaScript 脚本如何与 HTML 进行交互的 Web 标准。W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序动态地访问、更新文档的内容、结构和样式。
W3C DOM 标准被分为三个不同的部分:
如下图所示:
	
图 1 W3C文档对象模型
DOM 的历史可以追溯至 1990 年后期微软与 Netscape 的“浏览器大战”,双方为了在 JavaScript 与 JScript 之间一决生死,于是大规模赋予浏览器的强大功能。
在加载 HTML 页面时,Web 浏览器生成一个树形结构,用来表示页面内部结构。DOM 将这种树形结构理解为由节点组成的 DOM 树。DOM 规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等。
而第一个读取到的肯定是根标签 html,然后是它的子标签 head,再然后是 head 标签里的子标签等,以此类推直到遍历完所有的标签。因此从 html 标签开始,整个文档中的所有标签都会根据它们之间的父子关系被放到一个树形结构的对象中,如下图所示。
	
图 2 HTML标签转换为树形结构
树形结构包括父子关系,如下图所示:
	
图 3 父子关系
还包括先辈与后代的关系,如下图所示:
	
图 4 先辈与后代的关系
其中这个包含了所有标签对象的整个树形结构对象,就是 JavaScript 中的一个可以直接使用的内置对象——Document 对象。例如,下面的标签结构:
	
图 5 浏览器解析后的结果
整个文档中的一切都可以看作 Node 节点。各个组成部分的具体类型可以看作 Node 类型的子类。HTML 文档与 Node 节点之间的对应关系如下表所示。
	
严格来说,JavaScript 并不支持真正意义上的继承,这里我们借用 Java 中的继承概念,从逻辑上来帮助我们理解各个类型之间的关系。
1) 在整个文档范围内查询元素节点,如下表所示:
	
2) 在具体元素节点范围内查找子节点,如下表所示:
	
3) 查找指定元素节点的父节点,如下表所示:
	
4) 查找指定元素节点的兄弟节点,如下表所示:
	
使用 DOM 操作查找元素,示例代码如下:
	
图 6 DOM查询
1) 关于属性的操作,如下表所示:
	
2) 关于标签体的操作,如下表所示:
	
使用 DOM 操作属性和标签体,示例代码如下:
	
		
例如,创建一个城市列表,示例代码如下:
	
图 7 城市列表
在城市列表的最后添加一个子标签“长沙”,示例代码如下:
	
图 8 在城市列表的最后添加一个子标签“长沙”
还可以在城市列表中的“深圳”之前添加一个子标签“长沙”,示例代码如下:
	
图 9 在城市列表的深圳之前添加一个子标签“长沙”
在城市列表中添加一个子标签“长沙”替换深圳,示例代码如下:
	
图 10 在城市列表中添加一个子标签“长沙”替换深圳
在城市列表中删除子标签“深圳”,示例代码如下:
	
图 11 在城市列表中删除子标签“深圳”
最后,清除城市列表中的所有城市,保留城市列表标签 <ul>,示例代码如下:
	
	
这是一种非常常用的编程思想,将现实世界的事物抽象成模型,这样就很容易使用对象来量化描述现实事物,从而把生活中的问题转化成一个程序问题,最终实现用应用软件来协助解决现实问题。而模型就是连通现实世界和代码世界的桥梁。
DOM 是 W3C(World Wide Web Consortium)制订的一套技术规范,用来描述 JavaScript 脚本如何与 HTML 进行交互的 Web 标准。W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序动态地访问、更新文档的内容、结构和样式。
W3C DOM 标准被分为三个不同的部分:
- Core DOM 代表所有文档类型的标准模型;
- XML DOM 代表 XML 文档的标准模型;
- HTML DOM 代表 HTML 文档的标准模型。
如下图所示:

图 1 W3C文档对象模型
DOM 的历史可以追溯至 1990 年后期微软与 Netscape 的“浏览器大战”,双方为了在 JavaScript 与 JScript 之间一决生死,于是大规模赋予浏览器的强大功能。
在加载 HTML 页面时,Web 浏览器生成一个树形结构,用来表示页面内部结构。DOM 将这种树形结构理解为由节点组成的 DOM 树。DOM 规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等。
DOM树
浏览器把 HTML 文档从服务器下载后,就开始按照从上到下的顺序读取 HTML 标签。每个标签都会被封装成一个对象。而第一个读取到的肯定是根标签 html,然后是它的子标签 head,再然后是 head 标签里的子标签等,以此类推直到遍历完所有的标签。因此从 html 标签开始,整个文档中的所有标签都会根据它们之间的父子关系被放到一个树形结构的对象中,如下图所示。

图 2 HTML标签转换为树形结构
树形结构包括父子关系,如下图所示:

图 3 父子关系
还包括先辈与后代的关系,如下图所示:

图 4 先辈与后代的关系
其中这个包含了所有标签对象的整个树形结构对象,就是 JavaScript 中的一个可以直接使用的内置对象——Document 对象。例如,下面的标签结构:
<!DOCTYPE html>
<html lang="en">
<head>
    <title>文档标题</title>
</head>
<body>
    <a href="index.html">我的链接</a>
    <h1>我的标题</h1>
</body>
</html>
浏览器解析后得到的结果,如下图所示:
图 5 浏览器解析后的结果
整个文档中的一切都可以看作 Node 节点。各个组成部分的具体类型可以看作 Node 类型的子类。HTML 文档与 Node 节点之间的对应关系如下表所示。
| 组成部分 | 节点类型 | 具体类型 | 
|---|---|---|
| 整个文档 | 文档节点 | Document | 
| HTML 标签 | 元素节点 | Element | 
| HTML 标签内的文本 | 文本节点 | Text | 
| HTML 标签内的属性 | 属性节点 | Attribute | 
严格来说,JavaScript 并不支持真正意义上的继承,这里我们借用 Java 中的继承概念,从逻辑上来帮助我们理解各个类型之间的关系。
JavaScript DOM查询操作
由于实际开发时,基本上都是使用 JavaScript 的各种框架来操作,而框架中的操作方式和我们现在看到的原生操作完全不同,所以下面展示的 API 仅供参考,不做要求。1) 在整个文档范围内查询元素节点,如下表所示:
| 功能 | 具体方法 | 返回值 | 
|---|---|---|
| 根据 id 值查询 | document.getElementById("id 值") | 一个具体的元素节点 | 
| 根据标签名查询 | document.getElementsByTagName("标签名") | 元素节点数组 | 
| 根据 name 属性值查询 | document.getElementsByName("name 值") | 元素节点数组 | 
| 根据类名查询 | document.getElementsByClassName("类名") | 元素节点数组 | 
2) 在具体元素节点范围内查找子节点,如下表所示:
| 功能 | 具体方法 | 返回值 | 
|---|---|---|
| 查找子标签 | element.children | 子标签数组 | 
| 查找第一个子标签 | element.firstElementChild | 标签对象 | 
| 查找最后一个子标签 | element.lastElementChild | 节点对象 | 
3) 查找指定元素节点的父节点,如下表所示:
| 功能 | 具体方法 | 返回值 | 
|---|---|---|
| 查找指定元素节点的父标签 | element.parentElement | 标签对象 | 
4) 查找指定元素节点的兄弟节点,如下表所示:
| 功能 | 具体方法 | 返回值 | 
|---|---|---|
| 查找前一个兄弟标签 | 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 () {
          //从 div1 内搜索
          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>
运行代码查看页面效果,如下图所示:
图 6 DOM查询
JavaScript DOM元素属性与标签体操作
关于元素属性操作和标签文本值的操作具体如下:1) 关于属性的操作,如下表所示:
| 需求 | 操作方式 | 
|---|---|
| 读取属性值 | 元素对象.属性名 | 
| 修改属性值 | 元素对象.属性名=新的属性值 | 
2) 关于标签体的操作,如下表所示:
| 需求 | 操作方式 | 
|---|---|
| 获取标签体的文本内容 | element.innerText | 
| 获取标签体的内容 | element.innerHTML | 
| 设置标签体的文本内容 | 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>
运行代码,页面会输出:
hello world
JavaScript DOM增删改操作
使用 DOM 还可以对文档内容进行增删改操作,下面介绍一些常用的操作,如下表所示:| 功能 | 具体方法 | 
|---|---|
| 创建元素节点并返回,但不会自动添加到文档中 | document.createElement("标签名") | 
| 将 ele 添加到 element 所有子节点的后面 | element.appendChild(ele) | 
| 将 newEle 插入到 targetEle 前面 | parentEle.insertBefore(newEle,targetEle) | 
| 用新节点替换原有的旧子节点 | parentEle.replaceChild(newEle, oldEle) | 
| 删除某个标签 | element.remove() | 
例如,创建一个城市列表,示例代码如下:
<!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>
</body>
</html>
运行代码查看页面效果,如下图所示:
图 7 城市列表
在城市列表的最后添加一个子标签“长沙”,示例代码如下:
<!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 标签
        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);
    </script>
</body>
</html>
运行代码查看页面效果,如下图所示:
图 8 在城市列表的最后添加一个子标签“长沙”
还可以在城市列表中的“深圳”之前添加一个子标签“长沙”,示例代码如下:
<!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>
        //目标 2:在城市列表的深圳之前添加一个子标签 <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");
        //父.insertBefore(新标签,参照标签)
        cityUl.insertBefore(liElement, szElement);
    </script>
</body>
</html>
运行代码查看页面效果,如下图所示:
图 9 在城市列表的深圳之前添加一个子标签“长沙”
在城市列表中添加一个子标签“长沙”替换深圳,示例代码如下:
<!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>
        //目标 3:在城市列表中添加一个子标签 <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");
        //4. 获取到深圳这个标签
        var szElement = document.getElementById("sz");
        //父.replaceChild(新标签,被替换的标签)
        cityUl.replaceChild(liElement, szElement);
    </script>
</body>
</html>
运行代码查看页面效果,如下图所示:
图 10 在城市列表中添加一个子标签“长沙”替换深圳
在城市列表中删除子标签“深圳”,示例代码如下:
<!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>
        //目标 4:在城市列表中删除深圳
        //获取到深圳这个标签
        var szElement = document.getElementById("sz");
        szElement.remove();
    </script>
</body>
</html>
运行代码查看页面效果,如下图所示:
图 11 在城市列表中删除子标签“深圳”
最后,清除城市列表中的所有城市,保留城市列表标签 <ul>,示例代码如下:
<!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>
        //目标 5:清除城市列表中的所有城市,保留城市列表标签 <ul>
        var cityUl = document.getElementById("city");
        cityUl.innerHTML = "";
    </script>
</body>
</html>
运行代码后,发现页面没有任何城市列表信息。 
	 ICP备案:
 ICP备案: 公安联网备案:
 公安联网备案: