JavaScript的DOM之节点
关于JavaScript的DOM,其实vue和react这类框架已经帮我们解决了,学习本章的意义也是了解其原理,在一般开发中,很少直接操作dom,也不建议直接操作dmo
DOM基本概念
- DOM是JS操控HTML和CSS的桥梁
- DOM使JS操作HTML变得优雅
DOM简介
- DOM(Document Object Model,文档对象模型)是 JavaScript操作HTML文档的接口,使文档操作变得非常优 雅、简便
- DOM最大的特点就是将文档表示为节点树
DOM节点树
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>慕课网</h1> <div> <h2>程序员的梦工厂</h2> <img src="logo.png"> <div class="box"> 慕课专栏 </div> </div> </body></html>NodeType
节点的nodeType属性可以显示这个节点具体的类型
nodeType 值 | 节点类型 |
|---|---|
1 | 元素节点,例如 p 和 div |
3 | 文本节点 |
8 | 注释节点 |
9 | Document 文档节点 |
10 | DocumentType 文档类型节点(DTD) |
访问元素节点
- 所谓“访问”元素节点,就是指“得到”、“获取”页面上 的元素节点
- 对节点进行操作,第一步就是要得到它
- 访问元素节点主要依靠document对象
Document
-
document对象是DOM中最重要的东西,几乎所有DOM的 功能都封装在了document对象中
-
document对象也表示整个HTML文档,它是DOM节点树 的根
-
document对象的nodeType属性值是9
-
访问元素节点的常用方法
方法 功能 兼容性 document.getElementById()通过 ID 获取元素 IE6+ document.getElementsByTagName()通过标签名获取元素集合 IE6+ document.getElementsByClassName()通过类名获取元素集合 IE9+ document.querySelector()通过 CSS 选择器获取第一个匹配的元素 IE8 部分兼容,IE9+ 完全兼容 document.querySelectorAll()通过 CSS 选择器获取所有匹配的元素集合 IE8 部分兼容,IE9+ 完全兼容
获取节点
getElementById()
document.getElementById()功能是通过id得到元素节点
<div id="box">我是一个盒子</div><p id="para">我是一个段落</p><script>var box = document.getElementById('box');var para = document.getElementById('para');</script>注意事项
- 如果页面上有相同id的元素,则只能得到第一个
- 不管元素藏的位置有多深,都能通过id把它找到
getElementsByTagName()
getElementsByTagName()方法的功能是通过标签名得到 节点数组
<p>我是段落</p><p>我是段落</p><p>我是段落</p><p>我是段落</p><script>var ps = document.getElementsByTagName('p');//数组</script>注意事项
- 数组方便遍历,从而可以批量操控元素节点
- 即使页面上只有一个指定标签名的节点,也将得到长度为1 的数组
- 任何一个节点元素也可以调用getElementsByTagName() 方法,从而得到其内部的某种类的元素节点
getElementsByClassName()
getElementsByClassName()方法的功能是通过类名得到节点数组
<div class="spec">我是盒子</div><div>我是盒子</div><div class="spec">我是盒子</div><div class="spec">我是盒子</div><script>var spec_divs = document.getElementsByClassName('spec');</script>注意事项
- getElementsByClassName()方法从IE9开始兼容
- 某个节点元素也可以调用getElementsByClassName()方法 ,从而得到其内部的某类名的元素节点
querySelector()
querySelector()方法的功能是通过选择器得到元素
<div id="box1"><p>我是段落</p><p class="spec">我是段落</p><p>我是段落</p></div><script>var the_p = document.querySelector('#box1 .spec');</script>注意事项
- querySelector()方法只能得到页面上一个元素,如果有多 个元素符合条件,则只能得到第一个元素
- querySelector()方法从IE8开始兼容,但从IE9开始支持 CSS3的选择器,如
()、:[src^= ‘dog’]等CSS3选 择器形式都支持良好
querySelectorAll()
- querySelectorAll()方法的功能是通过选择器得到元素数组
- 即使页面上只有一个符合选择器的节点,也将得到长度为1 的数组
节点的关系
| 关系 | 考虑所有节点 |
|---|---|
| 子节点 | childNodes |
| 父节点 | parentNode |
| 第一个子节点 | firstChild |
| 最后一个子节点 | lastChild |
| 前一个兄弟节点 | previousSibling |
| 后一个兄弟节点 | nextSibling |
注意:文本节点也属于节点
- DOM中,文本节点也属于节点,在使用节点的关系时一定 要注意
- 在标准的W3C规范中,空白文本节点也应该算作节点,但 是在IE8及以前的浏览器中会有一定的兼容问题,它们不把 空文本节点当做节点
排除文本节点的干扰
-
从IE9开始支持一些“只考虑元素节点”的属性
关系 考虑所有节点 只考虑元素节点 子节点 childNodeschildren父节点 parentNodeparentElement第一个子节点 firstChildfirstElementChild最后一个子节点 lastChildlastElementChild前一个兄弟节点 previousSiblingpreviousElementSibling后一个兄弟节点 nextSiblingnextElementSibling
封装节点关系函数
书写常见的节点关系函数
-
书写IE6也能兼容的“寻找所有元素子节点”函数
-
书写IE6也能兼容的“寻找前一个元素兄弟节点”函数
-
如何编写函数,获得某元素的所有的兄弟节点?
<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");function getChildren(node) {var children = [];//结果数组//遍历node的所有子元素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));function getElementPrevSibling(node) {var o = node;while(o.previousSibling != null){if(o.previousSibling.nodeType === 1){return o.previousSibling;}o = o.previousSibling;}}console.log(getElementPrevSibling(para));function getAllElementSibling(node) {var prevs = [];var nexts = [];var o = node;while (o.previousSibling != null) {if (o.previousSibling.nodeType === 1) {prevs.unshift(o.previousSibling);}o = o.previousSibling;}o = node;while (o.nextElementSibling != null) {if (o.nextElementSibling.nodeType === 1) {nexts.push(o.nextElementSibling);}o = o.nextElementSibling;}return prevs.concat(nexts);}console.log(getAllElementSibling(para));</script></body>
哪些情况需要封装?
| 场景 | 是否需要封装 |
|---|---|
| 获取父元素 | 不需要 |
| 获取子元素 | 不需要 |
| 获取兄弟元素 | 不需要 |
| 获取第一个或最后一个子元素 | 不需要 |
| 查找符合条件的祖先元素 | 不需要 |
| 实现复杂的节点查找逻辑 | 可以封装 |
| 多处重复相同的 DOM 操作 | 可以封装 |
| 兼容 IE 等旧浏览器 | 视需求而定 |
节点操作
如何改变元素节点的CSS样式
-
改变元素节点的CSS样式需要使用这样的语句
oBox.style.backgroundColor ='red';//CSS属性要写成“驼峰”形式oBox.style.backgroundImage ='url(images/1.jpg)';//CSS属性值要设置成完整形式oBox.style.fontSize ='32px';//注意写单位
如何改变元素节点的HTML属性
-
标准W3C属性,如src、href等等,只需要直接打点进行更改即可
oImg.src = 'images/2.jpg'; -
不符合W3C标准的属性,要使用setAttribute()和getAttribute() 来设置、读取
oBox.setAttribute('data-n', 10);var n = oBox.getAttribute('data-n');alert(n);
innerHTML&innerText
如何改变元素节点中的内容
- 改变元素节点中的内容可以使用两个相关属性:①innerHTML ② innerText
- innerHTML属性能以HTML语法设置节点中的内容
- innerText属性只能以纯文本的形式设置节点中的内容
节点的创建、移除和克隆
节点的创建
-
document.createElement() 方法用于创建一个指定tag name的HTML元素
var oDiv = document.createElement('div');
孤儿节点
- 新创建出的节点是“孤儿节点”,这意味着它并没有被挂载 到DOM树上,我们无法看见它
- 必须继续使用appendChild()或insertBefore()方法将孤儿 节点插入到DOM树上
appendChild()
-
追加节点
-
任何已经在DOM树上的节点,都可以调用appendChild() 方法,它可以将孤儿节点挂载到它的内部,成为它的最后一 个子节点
父节点.appendChild(孤儿节点);
insertBefore()
-
任何已经在DOM树上的节点,都可以调用insertBefore() 方法,它可以将孤儿节点挂载到它的内部,成为它的“标杆 子节点”之前的节点
父节点.insertBefore(孤儿节点, 标杆节点);
示例:
请动态创建出一个20行12列的表格
function createTable() { var table = document.createElement("table"); for (var i = 0; i < 20; i++) { var row = document.createElement("tr"); for (var j = 0; j < 12; j++) { var cell = document.createElement("td"); cell.innerHTML = i + "-" + j; row.appendChild(cell); } table.appendChild(row); } document.body.appendChild(table);}createTable();请制作九九乘法表(可以在刚才代码基础上改动升级)
//制作九九乘法表function createTable1() { var table = document.createElement("table"); for (var i = 1; i <= 9; i++) { var row = document.createElement("tr"); for (var j = 1; j <= i; j++) { var cell = document.createElement("td"); cell.innerHTML = i + "x" + j + "=" + i * j; row.appendChild(cell); } table.appendChild(row); } document.body.appendChild(table);}createTable1();移动节点
-
如果将已经挂载到DOM树上的节点成为appendChild()或者 insertBefore()的参数,这个节点将会被移动
新父节点.appendChild(已经有父亲的节点);新父节点.insertBefore(已经有父亲的节点, 标杆子节点); -
这意味着一个节点不能同时位于DOM树的两个位置
删除节点
-
removeChild() 方法从DOM中删除一个子节点
父节点.removeChild(要删除子节点); -
节点不能主动删除自己,必须由父节点删除它
克隆节点
-
cloneNode() 方法可以克隆节点,克隆出的节点是“孤儿节 点
var 孤儿节点 = 老节点.cloneNode();var 孤儿节点 = 老节点.cloneNode(true); -
参数是一个布尔值,表示是否采用深度克隆:如果为true,则 该节点的所有后代节点也都会被克隆,如果为false,则只克 隆该节点本身
拓展-延迟执行
- 在测试DOM代码时,通常JS代码一定要写到HTML节点的 后面,否则JS无法找到相应HTML节点
- 可以使用window.onload = function(){} 事件,使页面加 载完毕后,再执行指定的代码
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














