JS_DOM

Javascript DOM

一、文档对象模型DOM

(一)理解DOM的作用

​ JS中的文档对象模型DOM(Document Object Model)的意义实际上是为了使用JS来操纵HTML页面,DOM将HTML文档中每个结点“映射”为一个对象,然后就可以在JS中使用面向对象的思维去操纵页面以及页面中的结点。HTML与DOM之间的关系可以理解为操作DOM就可以改变HTML页面的内容文档结构,而为HTML页面添加标签的话DOM也会作出一样的变化。将标签(HTML)“映射”为对象(JS)之后用JS操作对象的属性与方法,进而改变HTML的内容。DOM操作HTML结点,两者之间是相互映射的关系

Document:整个HTML页面文档

Object:将网页的每一部分转换为了一个对象(p标签、a标签…)

Model:使用模型来表示(结点/)对象之间的关系

(二)结点层次与常用结点

(1)结点层次

​ 结点层次分为Node类型Document类型Element类型Text类型、Comment类型、CDATA类型、DocumentType类型、DocumentFragment类型、Attr类型。

(2)结点的属性

每种类型的结点都会有nodeName、nodeType、nodeValue三种属性,随着结点类型的不同这三个属性的值也不尽相同。

(3)常用结点

  1. 文档节点:整个HTML文档

  2. 元素结点:HTML文档中的HTML标签

  3. 属性结点:元素的属性(a标签的src属性等)

  4. 文本结点:HTML标签中的文本内容

    image-20220119164250661

  5. Node类型结点

​ 结点是构成网页的基本组成部分,网页中的每个部分都可以看成是一个结点,比如HTML标签、属性、文本、整个文档都可以看成一个结点。但是这些结点的具体类型是不一样的,结点的属性与方法也不一样。每个节点可以看成是一个对象。(高程三里面称这些节点是对象)

  1. Document类型结点

    ​ document对象是HTMLDocument(继承自Document类型)的一个实例,同时document对象是window对象的一个属性,通过文档对象可以获取页面有关的信息(获取页面title),还可以操作页面的外观(使用JS改变样式)以及操作底层结构(使用JS改变HTML文档结构)

    ​ document类型的查找元素是DOM最常用的一个方面,用于获取特定某个(组)元素的引用,然后再执行一些操作,通过document对象的一些方法来完成页面元素的查找。返回的是对应HTML文档对应DOM中的结点对象的引用

    _1:**document.getElementById() ** ,通过元素id获取结点元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <button id="btn">我是一个按钮</button>
    </body>
    <script>
    var btn = document.getElementById("btn");
    console.log(btn.innerHTML); //我是一个按钮
    console.log(btn); //<button id="btn">我是一个按钮</button>
    console.log(typeof btn); //object

    btn.innerHTML = "I'm Button"; //按钮的内部文本改变为I'm Button
    </script>
    </html>

    _2:document.getElementsByTagName() ,通过标签名获取文档中所有的该名节点元素,返回nodeList,可以通过返回的nodeList用类似数组的方式访问这些标签的属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <img src="123">
    <img src="231">
    <img src="321">
    </body>
    <script>
    var images = document.getElementsByTagName("img");
    console.log(images);//HTMLCollection(3) [img, img, img]
    console.log(images.length);//3
    console.log(images[0].src);// 一长串的文件路径 /123
    console.log(images.item(1).src);// 一长串的文件路径 /231
    </script>
    </html>
  2. Element类型结点

    Element对象用于访问HTML元素标签名、子节点以及属性

    _1:访问元素标签名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <div id="myDiv"></div>
    </body>
    <script>
    //使用文档类型获取div结点的引用,获取到的是Element类型的元素
    var myDiv = document.getElementById("myDiv");
    console.log(myDiv.tagName); //DIV 获取标签名
    </script>
    </html>

    _2:获取结点属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <div id="myDiv"></div>
    </body>
    <script>
    //使用文档类型获取div结点的引用,获取到的是Element类型的元素
    var myDiv = document.getElementById("myDiv");
    console.log(myDiv.tagName); //DIV 获取标签名
    console.log(myDiv.getAttribute("id")); //myDiv
    myDiv.id = "herDiv"; //修改节点属性值
    console.log(myDiv.getAttribute("id")); //herDiv
    </script>
    </html>

    _3:创建元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <div id="myDiv"></div>
    </body>
    <script>
    var div = document.createElement("div"); //创建div结点
    div.id = "isDIV";
    console.log(div); // <div id="isDIV"></div>
    console.log(typeof div); // object
    console.log(div.id); //isDIV
    /*
    理解DOM与HTML文档结点的关系:使用方法创建的div方法返回的是一个对象,
    这从另一个角度看出HTML文档的结点对应着DOM里面的一个对象
    */
    /*通过ceateElement方法创建的HTML结点元素并没有挂载到HTML页面上,
    要通过其他的方法挂载*/
    </script>

    创建结点并挂载到HTML文档

    1
    document.body.appendChild(div);

    _4:元素子节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <ul id="myList">
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    <li>item 4</li>
    </ul>
    </body>
    <script>
    var myUl = document.getElementById("myList");
    console.log(myUl); //输出HTML元素结点
    console.log(myUl.childNodes.length); //9 4个<li> 4个文本 还有一个空白符(空格)
    for(let i=0;i<myUl.childNodes.length;i++){
    console.log(myUl.childNodes[i].nodeType); // 3 1 3 1 ...
    }
    console.log(myUl instanceof Object); //true
    console.log(myUl.childNodes instanceof Array); //false
    console.log(typeof myUl.childNodes); //object 并不是一个数组,而是一个对象
    </script>
    </html>
  3. Text类型结点(纯文本内容)

    _1:创建文本结点并修改文本内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <div id="isDIV">Hello guys</div>
    </body>
    <script>
    // 创建一个元素并为这个元素添加文本结点,然后挂载到页面上
    var myDIV = document.createElement("div"); //创建div结点
    myDIV.className = "myDIV"; //设置class名
    var textNode = document.createTextNode("Hello my friend"); //创建结点元素
    myDIV.appendChild(textNode); //将创建好的结点元素加载到DIV里面
    document.body.appendChild(myDIV); //将包装有文本结点的DIV挂载到页面上

    var isDIV = document.getElementById("isDIV");
    isDIV.firstChild.nodeValue = "Hello Morant!"; //修改已有结点的text文本
    </script>
    </html>

    image-20220122152159674

    _2:分割文本结点 (将一个文本结点分裂成两个文本结点)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>

    </body>
    <script>
    var tNode = document.createTextNode("Hello Guys");
    console.log(tNode.nodeValue); //Hello Guys

    var _tNode = tNode.splitText(5);

    console.log(tNode); // "Hello"
    console.log(_tNode); // "Guys"
    console.log(typeof tNode); // "object"
    console.log(typeof _tNode); // "object"
    </script>
    </html>
  4. Comment类型:DOM中注释也看成一个结点对象

  5. CDATASection类型:只针对于XML文档

  6. DocumentType类型、DocumentFragment类型。

  7. Attr类型:结点元素的属性也看做是一个对象,nodeName是属性名,nodeValue是属性值

(三)DOM操作技术

(1)动态脚本

​ 在页面加载时这段JS脚本是不存在的,当某些操作之后通过修改DOM触发动态生成脚本。(比如有一段JS代码需要某些操作之后才加载,这里的DOM思路是将外部写好的JS代码通过DOM动态生成HTML的script标签将其引入HTML文档中事项动态脚本);

_1:动态加载外部JS代码

1
<script type="text/javascript" src="client.js"></script>

_2:上面的JS标签结点对应的DOM代码

1
2
3
4
5
6
<script>
var script = document.createElement("script"); //创建标签结点
script.type = "text/javascript"; //设置标签结点的属性
script.src = "client.js";
document.body.appendChild(script); //挂载到HTML文档
</script>

ps: 这里应该更加理解DOM和HTML之间的关系,而不仅仅是直到有document那几个方法,DOM和HTML之间的关系是相互”映射”之间的关系,用不同的方式描述着同样的内容,HTML加入一个结点,DOM树对应地也加入了一个结点,DOM用代码的方式也可以为HTML文档加入HTML结点标签

(2)动态样式

同样的类似于创建动态脚本一样,也可以使用DOM来动态引入CSS样式,有两种方法,一种是类似于上面的方式外部写好的CSS动态创建标签引入样式表;另一种方式是用DOM实现嵌入式(直接写在HTML页面文档中)样式。(link引入外部CSS,style标签写嵌入式)

_1:动态加载外部样式表

1
<link rel="stylesheet" type="text/css" href="styles.css">

上面的JS标签结点对应的DOM代码

1
2
3
4
5
6
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "styles.css";
var head = document.getElementsByTagName("head")[0]; //获取第一个Head标签
head.appendChild(link); //CSS标签要加入到head中才可以生效

_2:DOM实现嵌入式CSS

1
2
3
4
5
<style type="text/css">
body{
background-color : red;
}
</style>

上面的CSS标签结点对应的DOM代码

1
2
3
4
5
var style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode("body{ background-color : red;}"));
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);

(3)操作表格

​ JS的DOM代码动态创建表格比直接使用HTML标签创建要多得多,感觉在日常开发中会很少用到,但是要用到的话直接上网找就好了

(4)使用NodeList、NamedNodeMap、HTMLCollection

​ DOM是JavaScript重要组成部分,在DOM中有三个特别的集合分别是NodeList(节点的集合),NamedNodeMap(元素属性的集合)和HTMLCollection(html元素的集合)。这三个集合有一些共同的特点:它们都可以通过中括号表达式来访问集合中元素,也有length属性。但它们并不是数组,而且它们都是动态的,会根据页面元素的变化而变化(类数组对象)

https://blog.csdn.net/u012207345/article/details/78165931

DOM操作是JS程序中开销最大的,会对程序的性能产生比较大的影响,尽量减少DOM操作


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!