一、DOM基本概念
1. DOM基本概念
- DOM是JS操控HTML和CSS的桥梁。
- DOM是JS操作HTML变得优雅。
DOM(Document Object Model,文档对象模型)
是JavaScript操作HTML文档的接口,使文档操作变得非常优雅、简便。- DOM最大的特点就是将文档表示为节点树。
- 节点的
nodeType
属性可以显示这个节点具体的类型。nodeType值 节点类型 1
元素节点,例如 <p>
和<div>
3
文字节点 8
注释节点 9
document节点 10
DTD节点
二、节点访问和位置关系
1. 访问元素节点
- 所谓"访问"元素节点,就是指"得到"、"获取"页面上的元素节点。
- 对节点进行操作,第一步就是要得到它。
- 访问元素节点主要依靠
document
对象。
-
认识
document
对象document
对象是DOM
中最重要的东西,几乎所有DOM的功能都封装在了document对象中
.document
对象也表示整个HTML文档
,它是DOM
节点树的根。document
对象的nodeType属性值是9
。
-
访问元素节点的常用方法
方法 功能 兼容性 document.getElementById()
通过 id
得到元素IE6 document.getElementByTagName()
通过 标签名
得到元素数组IE6 document.getElementByClassName()
通过 类名
得到元素数组IE9 document.querySelector()
通过 选择器
得到元素IE8部分兼容 IE9完全兼容 document.querySelectorAll()
通过 选择器
得到元素数组IE8部分兼容 IE9完全兼容 -
document.getElementById()
功能是通过id得到元素节点
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>// 给window对象添加onload事件监听。onload表示页面都加载完毕了。window.onload = function () {// 得到盒子1var box1 = document.getElementById('box1');// 得到盒子2var box2 = document.getElementById('box2');console.log(box1);console.log(box2);};</script> </head><body><div id="box1">我是盒子1</div><div id="box2">我是盒子2</div> </body></html>
- 参数就是元素节点的id,注意
不要写#号
通常JS代码一定要写到HTML节点的后面
,否则JS无法找到相应HTML节点。- 可以使用
window.onload = function(){}
事件,使页面加载完毕后,再执行指定的代码。 - 如果页面上
有相同id的元素,则只能得到第一个
- 不管元素藏的位置有多深,都能通过id把它找到。
- 参数就是元素节点的id,注意
-
document.getElementByTagName()
功能是通过标签名得到节点数组。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="box1"><p>我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><div id="box2"><p>我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><script>// 先得到box1var box1 = document.getElementById('box1');// 得到box1中的p标签的数组var ps_inbox1 = box1.getElementsByTagName('p');console.log(ps_inbox1);</script> </body> </html>
- 数组方便遍历,从而可以
批量操控元素节点
- 即使页面只有一个指定标签名的节点,也将得到
长度为1的数组
任何一个节点元素也可以调用getElementsByTagName()方法
,从而得到其内部的某种类的元素节点。
- 数组方便遍历,从而可以
-
document.getElementByClassName()
功能是通过类名得到节点数组
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div class="spec"><p>我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><div class="spec"><p>我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><script>// boxvar box = document.getElementsByClassName('spec');console.log(box);</script> </body> </html>
- 注意不要写
.
号 document.getElementByClassName()
方法从IE9开始兼容
。某个节点元素也可以调用document.getElementByClassName()方法
,从而得到其他内部的某类名的元素节点。
- 注意不要写
-
querySelector()
方法的功能是通过选择器得到元素<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="box1"><p class="spec">我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><script>var p = document.querySelector('#box1 .spec');console.log(p);</script> </body> </html>
querySelector()
方法只能得到页面上一个元素
,如果有多个元素符合条件,则只能得到第一个元素。querySelector()
方法从IE8开始兼容,但从IE9开始支持CSS3的选择器
,但从IE9开始支持CSS3的选择器
,
如:nth-child()
、:[src^='dog']
等CSS3选择器形式都支持良好。
-
querySelectorAll()
方法的功能是通过选择器得到元素数组
。- 即使页面上只有一个符合选择器的节点,也将得到长度为
1
的数组
- 即使页面上只有一个符合选择器的节点,也将得到长度为
2. 节点的关系
关系 | 考虑所有节点 |
---|---|
子节点 | childNodes |
父节点 | parentNodes |
第一个子节点 | fristChild |
最后一个子节点 | lastChild |
前一个兄弟节点 | previousSibling |
后一个兄弟节点 | nextSibling |
-
DOM中,文本节点也属于节点,在使用节点的关系时一定要注意
-
在标准的W3C规范中,空白文本节点也应该算作节点
,但是在IE8及以前的浏览器会有一定的兼容问题,它们不把空白文本节点当做节点。 -
排除文本节点的干扰,从IE9开始支持一些"只考虑元素节点"的属性
关系 考虑所有节点 只考虑元素节点 子节点
childNodes
children
父节点
parentNodes
children
第一个子节点
fristChild
fristElementChild
最后一个子节点
lastChild
lastElementChild
前一个兄弟节点
previousSibling
previousElementSibling
后一个兄弟节点
nextSibling
nextElementSibling
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="box"><p>我是段落A</p><p id="para">我是段落B</p><p>我是段落C</p></div><script>var box = document.getElementById('box');var para = document.getElementById('para');// 所有子节点console.log(box.childNodes);// 所有的元素子节点(IE9开始兼容)console.log(box.children);// 第一个子节点console.log(box.firstChild);console.log(box.firstChild.nodeType);// 第一个元素子节点(IE9开始兼容)console.log(box.firstElementChild);// 最后一个子节点console.log(box.lastChild);console.log(box.lastChild.nodeType);// 最后一个元素子节点(IE9开始兼容)console.log(box.lastElementChild);// 父节点console.log(para.parentNode);// 前一个兄弟节点console.log(para.previousSibling);// 前一个元素兄弟节点(IE9开始兼容)console.log(para.previousElementSibling);// 后一个兄弟节点console.log(para.nextSibling);// 后一个元素兄弟节点(IE9开始兼容)console.log(para.nextElementSibling);</script> </body> </html>
-
IE6也能兼容的"寻找所有元素子节点"函数
-
IE6也能兼容的"寻找前一个元素兄弟节点"函数
-
获取某元素的所有兄弟节点
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head><body><div id="box"><p>我是段落</p><p>我是段落</p><p>我是段落</p><p id="fpara">我是段落fpara</p>我是文本<!-- 我是注释 --><p id="para">我是段落para<span>1</span><span>2</span><span>3</span></p><p>我是段落</p><p>我是段落</p><p>我是段落</p></div><script>var box = document.getElementById('box');var para = document.getElementById('para');var fpara = document.getElementById('fpara');// 封装一个函数,这个函数可以返回元素的所有子元素节点(兼容到IE6),类似children的功能function getChildren(node) {// 结果数组var children = [];// 遍历node这个节点的所有子节点,判断每一个子节点的nodeType属性是不是1// 如果是1,就推入结果数组for (var i = 0; i < node.childNodes.length; i++) {if (node.childNodes[i].nodeType == 1) {children.push(node.childNodes[i]);}}return children;}console.log(getChildren(box));console.log(getChildren(para));// 封装一个函数,这个函数可以返回元素的前一个元素兄弟节点(兼容到IE6),类似previousElementSibling的功能function getElementPrevSibling(node) {var o = node;// 使用while语句while (o.previousSibling != null) {if (o.previousSibling.nodeType == 1) {// 结束循环,找到了return o.previousSibling;}// 让o成为它的前一个节点,就有点“递归”的感觉o = o.previousSibling;}return null;}console.log(getElementPrevSibling(para));console.log(getElementPrevSibling(fpara));// 封装第三个函数,这个函数可以返回元素的所有元素兄弟节点function getAllElementSibling(node) {// 前面的元素兄弟节点var prevs = [];// 后面的元素兄弟节点var nexts = [];var o = node;// 遍历node的前面的节点while(o.previousSibling != null) {if(o.previousSibling.nodeType == 1){prevs.unshift(o.previousSibling);}o = o.previousSibling;}o = node;// 遍历node的后面的节点while(o.nextSibling != null) {if(o.nextSibling.nodeType == 1){nexts.push(o.nextSibling);}o = o.nextSibling;}// 将两个数组进行合并,然后返回return prevs.concat(nexts);}console.log(getAllElementSibling(para));</script> </body></html>
三、节点操作
1. 节点操作
-
如何改变元素节点中的内容
- 改变元素节点中的内容可以使用两个相关的属性:
- innerHTML
- innerText
- innerHTML属性能
以HTML语法
设置节点中的内容。 - innerText属性只能
以单纯文本的形式
设置节点中的内容。<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="box"></div><script>var oBox = document.getElementById('box');oBox.innerHTML = '张三';oBox.innerHTML = '<ul><li>牛奶</li><li>咖啡</li></ul>';</script> </body> </html>
- 改变元素节点中的内容可以使用两个相关的属性:
-
如何改变元素节点的CSS样式
- 改变元素节点的CSS样式需要使用这样的语句
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box{width: 200px;height: 200px;border: 1px solid #000;}</style> </head> <body><div class="box" id="box">你好</div><script>var oBox = document.getElementById('box');// oBox.style.backgroundColor = 'rgb(100, 200, 123)';// oBox.style.backgroundColor = '#f80';// oBox.style.backgroundImage = 'url(https://www.imooc.com/static/img/index/logo-recommended.png)';// oBox.style.backgroundSize = 'contain';oBox.style.fontSize = '50px';</script> </body> </html>
- 改变元素节点的CSS样式需要使用这样的语句
-
如何改变元素节点的HTML属性
-
标准W3C属性,如src、href等等,只需要直接打点进行更改即可
-
不符合W3C标准的属性,要使用
setAttribute()
和getAttribute()
来设置、读取<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><img src="images/1.jpg" id="pic"><a href="http://www.baidu.com" id="link">去百度</a><script>var oPic = document.getElementById('pic');var oLink = document.getElementById('link');oPic.src = 'images/2.jpg';oLink.href = 'http://www.baidu.com';oLink.innerText = '去百度';</script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="box"></div><script>var box = document.getElementById('box');box.setAttribute('data-n', 10);var n = box.getAttribute('data-n');alert(n);</script> </body> </html>
-
2. 节点创建
-
document.createElement()
方法用于创建一个指定tagName
的HTML元素 -
孤儿节点
- 新创建的节点是"孤儿节点",这意味着它
并没有被挂载到DOM树上
,我们无法看到它。 - 必须继续使用
appendChild()
或者insertBefore()
方法将孤儿节点插入到DOM树上。
- 新创建的节点是"孤儿节点",这意味着它
-
appendChild()
方法- 任何已经在DOM树上的节点,都可以调用
appendChild()
方法,它可以将孤儿节点挂载到它的内部,成为它的最后一个子节点
- 任何已经在DOM树上的节点,都可以调用
-
insertBefore()
方法- 任何已经在DOM树上的节点,都可以调用insertBefore()方法,它可以将孤儿节点挂载到它的内部,成为它的"标杆子节点"之前的节点
3. 移动节点
- 如果将已经挂载到DOM树上的节点成为
appendChild()
或者insertBefore()
的参数,这个节点将会被移动 - 这意味着一个节点不能同时位于DOM树的两个位置
4. 删除节点
removeChild()
方法从DOM中删除一个子节点- 节点不能主动删除自己,必须由父节点删除它
5. 克隆节点
cloneNode()
方法可以克隆节点,克隆出的节点是"孤儿节点"- 参数是一个布尔值,表示
是否采用深度克隆
:如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克
隆该节点本身