DOM简介
「1.1什么是DOM」
文档对象模型(Document Object Model ,简称DOM),是W3C组织推荐的处理扩展标记语言(HTML或者XML)的编程接口。
W3C已经定义了一系列的DOM接口,通过这些接口可以改变网页的内容,结构和样式。
- 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的DOM编程接口
- 对于HTML,DOM使得HTML形成了一颗DOM树,包含文档,元素,节点。
- 我们获取过来的DOM元素是一个对象(Object),所以称为 文档对象模型
「1.2DOM树」

- 文档:一个页面就是一个文档,DOM中用document表示
- 元素:页面中所有标签都是元素,DOM中用element表示
- 节点:网页中所有内容都是节点(标签,属性,文本,注释),DOM中使用node表示
DOM把以上内容都看作是对象
获取元素
「2.1如何获取页面元素」
DOM在实际开发中主要用来操作元素
有如下几种方式
- 根据ID获取
- 根据标签名获取
- 通过HTML5新增方法获取
- 特殊元素获取
「2.2根据id」
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // document.getElementById('id名'); <div id="time">2022</div> <script> var timer = document.getElementById('time'); console.log(timer); console.log(typeof timer); console.dir(timer); </script>
|
「2.3根据标签名」
返回的是带有指定标签名的对象的集合
- 因为是集合,所以使用时要遍历
- 得到元素对象是动态的
1
| document.getElementsByTagName('标签名');
|
还可以获取某个元素(父元素)内部所有指定标签名的子元素,父元素必须是单个对象(必须指明是哪一个元素对象),获取时不包括父元素自己
1 2
| element.getElementByTagName('标签名');
|
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 29 30 31 32 33 34 35 36
| // document.getElementsByTagName('标签名'); // element.getElementsByTagName('标签名'); <body> <ul> <li>知否知否应是等你好久1</li> <li>知否知否应是等你好久2</li> <li>知否知否应是等你好久3</li> <li>知否知否应是等你好久4</li> <li>知否知否应是等你好久5</li> </ul> <ol id = "ol"> <li>生僻字</li> <li>生僻字</li> <li>生僻字</li> <li>生僻字</li> <li>生僻字</li> </ol> <script> var lis = document.getElementsByTagName('li'); console.log(lis); console.log(lis[0]); for (var i = 0;i < lis.length; i++) { console.log(lis[i]); }
var ol = document.getElementsByTagName('ol'); console.log(ol[0].getElementsByTagName('li')); var ol = documnet.getElementsById('ol'); console.log(ol.getElementsByTagName('li')); </script> </body>
|
「2.4通过H5获取」
1
| document.getElementsByClassName('类名');
|
1
| document.querySelector('选择器');
|
1
| documnet.querySelectorAll('选择器');
|
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
| <body> <div class="box">盒子1</div> <div class="box">盒子2</div> <div id="nav"> <ul> <li>首页</li> <li>产品</li> </ul> </div> <script> var boxs = documnet.getElementsByClassName('box'); console.log(boxs); var firstbox = document.querySelector('.box'); console,log(firstbox); var nav = documnet.querySelector('#nav'); console.log(nav); var li = documnet.querySelector('li'); console.log(li); var allBox = document.querySelectorAll('.box'); console.log(allBox); </script> </body>
|
「2.5获取特殊元素(body,html)」
获取body元素
获取html元素
1
| document.documentElement
|
1 2 3 4 5 6 7 8 9 10 11
| <body> <script> var bodyEle = document.body; console.log(bodyEle); console.dir(bodyEle); var htmlEle = document.documentElement; console.log(htmlEle); </script> </body>
|
事件基础
「3.1事件概述」
JavaScript使我们有能力创建静态页面,而事件是可以被JavaScript侦测搭配的行为
简单理解:触发….响应机制
网页中每个元素都可以产生某些可以触发JavaScript的事件,例如我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作
「3.2事件三要素」
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <botton id="btn">唐伯虎</botton> <script> var btn = document.getElementById('btn'); btn.onclick = function() { alert('点秋香'); } </script> </body>
|
「3.3执行事件的步骤」
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
常见鼠标事件
| 鼠标事件 |
触发条件 |
| onclick |
鼠标点击左键触发 |
| onmouseover |
鼠标经过触发 |
| onmouseout |
鼠标离开触发 |
| onfocus |
获得鼠标焦点触发 |
| onblur |
失去鼠标焦点触发 |
| onmousemove |
鼠标移动触发 |
| onmouseup |
鼠标弹起触发 |
| onmousedown |
鼠标按下触发 |
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <div>盒子</div> <script> var div = document.querySelector('div'); div:onmouseover = function() { alert ('我被选中了'); } </script> </body>
|
操作元素
JavaScript的DOM操作可以改变网页内容,结构和样式,我们可以利用DOM操作元素里面的内容属性等。注意一下都是属性。
「4.1改变元素内容」
案例:改变元素内容
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 29 30 31 32 33 34 35 36 37
| <style> div,p { width: 300px; height: 30px; line-height: 30px; color: #fff; background-color: pink; } </style>
<body> <botton>显示系统当前时间</botton> <div>某个时间</div> <p>123</p> <script> var btn = document.querySelector('button'); var div = document.querySelector('div'); btn:onclick = function() { div.innerHTML = getDate(); } function getDate() { var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; var dates = date.getDate(); var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; var day = date.getDay(); return '今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]; } var p = document.querySelector('p'); p.innerHTML = getDate(); </script> </body>
|
「4.2常用元素的属性操作」
1 2 3 4
| innerText innerHTML 改变元素内容 src href id alt title 加一个 . 符号
|
案例:分时显示图片,显示不同问候语
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 29 30 31
| <body> // 根据系统不同时间判断 // 利用多分支语句设置不同的图片内容 // 需要一个图片,并根据时间修改图片,操作元素属性 // 需要div元素显示不同问候语 <img src="#" alt="好" title="上午好"> <div>好好写代码</div> <script>
var img = document.querySelector('img'); var div = document.querySelector('div'); var date = new Date(); var h = date.getHours(); if(h < 12) { img.src = '#'; img.title = '上午好'; div.innerHTML = '亲,上午好,好好写代码'; } else if(h < 18) { img.src = '#'; img.title = '下午好'; div.innerHTML = '亲,下午好,好好写代码'; } else { img.src = '#'; img.title = '晚上好'; div.innerHTML = '亲,晚上好,好好写代码'; } </script> </body>
|
「4.3表单元素属性操作」
1 2
| 利用DOM可以操作如下表单元素属性 type value checked selected disabled
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <body> <button>按钮</button> <input type="text" value="输入内容"> <script> var btn = document.querySelector('button'); var input = document.querySelector('input'); btn:onclick = function() { input.value = '被点击了'; this.disabled = true; } </script> </body>
|
案例:仿京东显示隐藏密码
分析:
- 核心思路:点击眼睛按钮,把密码框类型改为文本框就可以看见里面的密码
- 一个按钮两个状态,点击一次,切换为文本框,继续点击切换为密码框
- 算法:利用flag变量,来判断flag值,如果是1就切换为文本框,flag设置为0,如果是0就切换为密码框,flag设置为1
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <style> .box { position: relative; width: 400px; border-bottom: 1px solid #ccc; margin: 100px auto; } .box input { width: 370px; height: 30px; border: 0; outline: none; } .box img { position: absolute; top: 10px; right: 5px; width: 24px; } </style> </head> <body> <div class="box"> <lable for=""> <img src="img/noeye.png" alt="无" id="eye"> </lable> <input type="passworld" name="" id="pwd"> </div> <script> var eye = document.getElementById('eye'); var pwd = document.getElementById('pwd'); var flag = 0; eye.onclick = function() { if(flag == 0) { pwd.type = 'text'; eye.src = 'img/eye.png'; flag = 1; } else { pwd.type = 'password'; eye.src = 'img/noeye.png'; flag = 0; } } </script> </body>
|
「4.4样式属性操作」
我们可以通过JS修改元素大小,颜色,位置等样式
1 2
| element.style.属性 element.className
|
注意:
- 如果样式修改较多,可以采用操作类名方式更改元素样式
- class是一个保留字,因此使用className来操作类名属性
- className会直接更改元素类名,会覆盖原先的类名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <body> <div class="first">文本</div> <script>
var test = document.querySelector('div'); test:onclick = function() { this.style.backgroundColor = 'purple'; this.style.color = '#fff'; this.style.fontSize = '25px'; this.style.marginTop = '100px';
this.className = 'change'; this.className = 'first change'; } </script> </body>
|

「4.5排他思想」
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法
- 给所有元素全部清除样式(干掉其他人)
- 给当前元素设置样式(留下我自己)
- 注意顺序不能颠倒,首先干掉其他人,在设置自己
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> var btns = document.getElementsByTagName('button'); for(var i = 0; i < btns.length; i++) { btns[i].onclick = function() { for(var i = 0; i < btns.length; i++) { btns[i].style.backgroundColor = ''; } this.style.backgroundColor = 'pink'; } } </script> </body>
|
案例:百度换肤效果
- 这个案例是给一组元素注册事件
- 给四个小图片利用循环注册点击事件
- 当我们点击了这个图片,让我们背景颜色改为当前的图片
- 核心算法:把当前图片的src 路径取过来,给body 作为背景即可
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <style> *{ margin: 0; padding: 0; } body{ background: url(img/1.jpg) no-repeat center top; } li { list-style: none; } .baidu { overflow: none; margin: 100px auto; background-color: #fff; width: 400px; padding-top: 3px; } .baidu li{ float:left; margin: 0 1px; cursor: pointer; } .baidu img { width: 100px; } </style> <body> <ul class="baidu"> <li><img src="img/1.jpg" alt="无图片1"></li> <li><img src="img/2.jpg" alt="无图片2"></li> <li><img src="img/3.jpg" alt="无图片3"></li> <li><img src="img/4.jpg" alt="无图片4"></li> </ul> <script> var imgs = document.querySelector('.baidu').querySelectorAll('img'); for (var i = 0; i < imgs.length; i++) { imgs[i].onclick = function() { document.body.style.backgroundImage = 'url('+ this.src +')'; } } </script> </body>
|
案例:表格隔行变色效果
- 用到鼠标经过事件和鼠标离开事件
- 核心思路:鼠标经过tr行,当前行变背景颜色,鼠标离开去掉当前背景颜色
- 注意:第一行(thead里面的行)不需要变换颜色
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <style> table{ width: 800px; margin: 100px auto; text-align: center; border-collapse: collapse; font-size: 14px; } thead tr { height: 30px; background-color: skyblue; } tbody tr { height: 30px; } tbody td{ border-bottom: 1px solid #d7d7d7; font-size: 12px; color: blue; } .bg { background-color: pink; } </style> <body> <table> <thead> <tr> <td>代码</td> <td>名称</td> <td>最新公布净值</td> <td>累计净值</td> <td>前单位净值</td> <td>净值增长率</td> </tr> </thead> <tbody> <tr> <td>003526</td> <td>农银金辉</td> <td>1.075</td> <td>1.254</td> <td>1.548</td> <td>1.5556</td> </tr> <tr> <td>003526</td> <td>农银金辉</td> <td>1.075</td> <td>1.254</td> <td>1.548</td> <td>1.5556</td> </tr> </tbody> </table> <script>
var trs = document.querySelector('tbody').querySelectorAll('tr');
for(var i = 0; i < trs.length; i++) { trs[i].onmouseover = function() { this.className = 'bg'; } trs[i].onmouseout = function() { this.className = ''; } } </script> </body>
|
案例:全选或反选
- 全选或取消全选的做法:让下面的所有复选框的checked属性(选中状态)跟随全选按钮即可
- 下面复选框需要全部选中,上面全选才能选中的做法:给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有复选框是否有未选中的,如果有一个未选中的,上面的全选就不选中
- 可以设置一个变量,来控制全选是否选中
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <style> table{ width: 800px; margin: 100px auto; text-align: center; font-size: 14px; } </style> <body> <table> <thead> <tr> <td><input type="checkbox" id="j_cbAll"></td> <td>商品</td> <td>价格</td> </tr> </thead> <tbody id="j_tb"> <tr> <td><input type="checkbox"></td> <td>iPhone6</td> <td>8000</td> </tr> <tr> <td><input type="checkbox"></td> <td>ipad</td> <td>5000</td> </tr> <tr> <td><input type="checkbox"></td> <td>watch</td> <td>2000</td> </tr> </tbody> </table> <script> var j_cbAll = document.getElementById('j_cbAll'); var j_tb = document.getElementById('j_tb').getElementsByTagName('input'); j_cbAll.onclick = function() { console.log(this.checked); for(var i = 0; i < j_tb.length; i++) { j_tb[i].checked = this.checked; } } for(var i = 0; i < j_tb.length; i++) { j_tb[i].onclick = function() { var flag = true; for(var i = 0; i < j_tb.length; i++) { if(!j_tb[i].checked) { flag = false; break; } } j_cbAll.checked = flag; } }
</script> </body>
|
「4.6自定义属性操作」
1.获取元素属性
- element.属性; 获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’); 主要获取自定义属性
2.设置属性值
- element.属性 = ‘值’ ; 设置内置属性值
- element.getAttribute(‘属性’, ‘值’); 主要设置自定义属性
3.移除属性
- element.removeAttribute(‘属性’);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <div id="demo" index="1" class="nav"></div> <script> var div = document.querySelector('div'); console.log(div.id); console.log(div.getAttribute('id')); console.log(div.getAttribute('index')); div.id = 'test'; div.className = 'navs'; div.setAttribute('index','2'); div.setAttribute('class','footer'); div.removeAttribute('index'); </script>
|
「4.7 H5自定义属性」
自定义属性目的:为了保存并使用数据,有些数据可以保存到页面中而不用保存在数据库中
有些自定义属性容易引起歧义,不容易判断是否是元素的内置属性还是自定义属性,所以H5新增了自定义属性
1.设置H5自定义属性
H5规定自定义属性必须以**data-**开头作为属性名并赋值
2.获取H5自定义属性
- 兼容性获取 element.getAttribute(‘data-index’)
- H5新增 element.dataset.index或者 element.dataset[‘index’]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <div getTime="20" data-index="2" data-list-name="andy"></div> <script> console.log(div.getAttribute('getTime')); div.setAttribute('data-time','20'); console.log(div.getAttribute('data-index')); console.log(div.getAttribute('data-list-name')); console.log(div.dataset); console.log(div.dataset.index); console.log(div.dataset['index']); console.log(div.dataset.listName); console.log(div.dataset['listName']); </script>
|
案例:tab栏切换
节点操作
「5.1为什么学节点操作」
获取元素通常使用两种方式
- 利用DOM提供的方法获取元素
- 利用节点层级关系获取元素
「5.2节点概述」
网页中所有内容都是节点(标签,属性,文本,注释等),在DOM中,节点使用node表示。
HTML DOM树中所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除

一般的,节点至少拥有nodeType(节点类型),nodeName(节点名称),nodeValue(节点值)这三个基本属性
- 元素节点 nodeType 为1
- 属性节点 nodeType 为2
- 文本节点 nodeType 为3
实际开发中,节点操作主要操作元素节点
「5.3节点层级」
利用DOM树可以把节点划分成不同的层级关系,常见的是父子兄层关系
1.父级节点
- parentName 属性可返回某节点的父节点件,注意是最近的一个父节点
- 如果指定的节点没有父节点则返回null
1 2 3 4 5 6 7 8 9 10
| <div class="demo"> <div class="box"> <span class="erweima"></span> </div> </div> <script> var erweima = document.querySelector('.erweima'); console.log(erweima.parentNode); </script>
|
2.子节点
返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:
返回值里包含所有的节点,包括元素节点,文本节点等
如果只要获取元素节点,需要专门处理,所以一般不提倡使用childNodes
1 2 3 4 5 6 7
| var ul = document.querySelector('ul'); for (var i = 0;i < ul.childNodes.length; i++) { if(ul.childNodes[i].nodeType = 1) { console.log(ul.childNodes[i]); } }
|
parentNode.chileren 是一个只读属性,返回所有子元素节点,它只返回子元素节点,其余节点不返回(这是我们重点掌握的)
虽然children是一个非标准,但得到各个浏览器支持
1 2
| 3.parentNode.firstChild 4.parentNode.lastChild
|
返回第一个(最后一个)子节点,找不到返回null,同样返回的是所有节点
1 2
| 5.parentNode.firstElementChild 6.parentNode.lastElementChild
|
返回的是第一个(最后一个)子元素节点,找不到返回null
案例:下拉菜单
3.兄弟节点
1 2
| node.nextSibling node.previousSibling
|
返回的是当前元素的下一个(上一个)兄弟节点,找不到则返回null, 是包含所有节点
1 2
| node.nextElementSibling node.previousElementSibling
|
返回的是当前元素的上一个(下一个)兄弟元素节点,找不到返回null
「5.4创建与添加节点」
创建节点
1
| document.createElement('tagName')
|
document.createElement(‘tagName’)方法创建由tagName指定的HTML元素,因为这些元素原先不存在,是根据我们的需求动态产生的,所以也称之为动态创建元素节点
添加节点
node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。类似CSS的after伪元素
1
| node.inserBefore(child,指定元素)
|
node.inserBefore(child,指定元素)方法将一个节点添加到父节点的指定子节点的前面,类似CSS的before伪元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <ul> <li>123</li> </ul> <script> var li = document.createElement('li'); var ul = document.querySelector('ul'); ul.appendChild(li); var lili = documentquerySelector('li'); ul.inserBefore(lili,ul.children[0]); </script>
|
案例:简单版发布留言
「5.5删除节点」
node.removeChild()方法从DOM中删除一个子节点,返回删除的节点
1 2 3 4 5 6 7 8 9
| <ul> <li></li> <li></li> <li></li> </ul> <script>
</script>
|
案例:删除留言板
「5.6复制节点(克隆节点)」
node.cloneNode() 方法返回调用该方法的节点的一个副本,也称为克隆节点或者复制节点
注意:
- 如果括号内参数为空或者false,则是浅拷贝,只克隆复制节点本身,不克隆里面的字节点
- 如果括号内参数为true,则是深拷贝,会克隆复制节点本身以及里面所有的子节点
案例:动态生成表格
「5.8三种动态创建元素的区别」
- document.write()
- element.innerHTML()
- document.createElement()
区别:
- document.write() 是直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面全部重绘
- innerHTML() 是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML() 创建多个元素效率更高(不要拼接字符串,采取数组的形式拼接),结构稍微复杂
- createElement() 创建多个元素效率稍微低一点,但是结构清晰
- 不同浏览器下,innerHTML比createELement效率高
DOM重点核心
关于DOM操作,我们主要针对于元素的操作,主要有创建,增,删,改,查,属性操作,事件操作
「6.1创建」
- document.write
- innerHTML
- createELement
「6.2增」
- appendChild
- insertBefore
「6.3删」
- removeChild
「6.4改」
主要修改DOM的元素属性,DOM元素的内容,属性,表单的值等
- 修改元素属性:src,href,title等
- 修改普通元素内容:innerHTMl,innerText
- 修改表单元素:value,type,disabled等
- 修改元素样式:style,className
「6.5查」
主要获取查询DOM元素
- DOM提供的API方法:getElementById, getElementByTagName, 古老用法不太推荐
- H5提供的新方法:querySelector, querySelectorAll 提倡使用
- 利用节点操作获取元素:父(parentNode), 子(children), 兄(previousElementSibling, nextElementsibling) 推荐使用
「6.6属性操作」
主要针对自定义属性
- setAttribute: 设置DOM的属性值
- getAttribute: 得到DOM的属性值
- removeAttribute: 移除属性
「6.7事件操作」
给元素注册事件,采取
事件源. 事件类型 = 事件处理程序