在JavaScript中,DOM节点操作是非常常见的基础交互功能,这是构建网页交互层的基础。本文总结了有关于DOM节点操作常见的操作,供大家方便查阅。
什么是 DOM?
文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将 web 页面和脚本或程序语言连接起来。——MDN——什么是 DOM?
白话文:DOM是浏览器提供的用来操作网页内容的功能
DOM树
将HTML文档以树状结构直观的表现出来,称之为文档树或 DOM树
作用:文档树直观的体现了标签与标签之间的关系
DOM对象
DOM对象:浏览器根据html标签自动生成的js对象
- 所有的标签属性都可以在这个对象上面找到
- 修改这个对象的属性会自动映射到对象标签上
DOM核心思想:
- 把网页当作对象来处理
document对象:
- DOM提供的对象
- 其提供的属性和方法都是用于操作网页内容的
- 网页所有内容都在document里
DOM节点
DOM树中的每个内容都称为节点
节点类型:
- 元素节点(重点)
- 所有的标签比如body、div
- html为根节点
- 属性节点
- 所有的属性比如href属性
- 文本节点
- 所有的文本
- 其他
获取DOM元素
1 匹配满足条件的第一个元素
语法:
document.querySelector('css选择器')
参数:
包含一个或者多个有效的css选择器
返回:
返回匹配的第一个html元素
|
|
2 匹配满足条件的多个元素
语法:
document.querySelectorAll('css选择器')
参数:
包含一个或者多个有效的css选择器
返回:
返回匹配的Nodelist
的集合(注:NodeList
是一个伪数组,要想得到里面的元素可以通过for循环的方式获得)
注意:这里如果即便只有一个元素满足条件,返回的也是NodeList
|
|
3 根据id获取一个元素
document.getElementById('mark')
4 根据标签获取一个元素
document.getElementByTagName('div')
5 根据类名获取元素 获取页面所有类名为 xxx 的元素
document.getElemntByClassName('xxx')
查找节点
查找父节点
- 通过
parentNode
属性获取 - 返回最近的父节点,如果不存在则返回
null
- 语法:
document.querySelector('#patty').parentNode;
查找子节点
-
childNodes
属性(不推荐使用)- 获得所有的子节点,包括文本节点(空格、换行)、注释节点等
-
children
属性-
获取所有的子元素节点
-
返回值为一个
HTMLCollection
,这是一个伪数组。1 2 3 4 5 6 7 8 9 10 11 12 13
<ul> <li>1</li> <!-- 注释节点 --> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> let ul = document.querySelector('ul'); console.log(ul.childNodes); // NodeList(13) console.log(ul.children); // HTMLCollection(5) [li, li, li, li, li] </script>
-
查找兄弟节点
-
获取下一个兄弟节点
nextElementSibling
属性
-
获取上一个兄弟节点
previousElementSibling
属性
-
补充
nextSibling
与previousSibling
-
会将空格或者换行当做节点处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
<div id="previous"> 卧槽不是吧 </div> <ul> <li>1</li> <!-- 注释节点 --> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <div id="nest"> 明华大鼬 </div> <script> let ul = document.querySelector('ul'); console.log(ul.previousElementSibling); // div#previous console.log(ul.nextElementSibling); // div#nest // nextSibling,previousSibling都会将空格或者换行当做节点处理 console.log(ul.previousSibling); // text console.log(ul.previousSibling.previousSibling); // div#previous console.log(ul.nextSibling); // text console.log(ul.nextSibling.nextSibling); // div#next </script>
-
查找第一个节点|最后一个节点
-
查找第一个节点
- 属性
firstElementChild
- 如果子元素不存在则返回
null
- 属性
-
查找最后一个节点
- 属性
lastElementChild
- 如果子元素不存在则返回
null
- 属性
-
补充
firstChild
与lastChild
-
会将空格或者换行当做节点处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
<ul> 114514 <li>1</li> <!-- 注释节点 --> <li>2</li> <li>3</li> <li>4</li> <li>5</li> 1919810 </ul> <script> let ul = document.querySelector('ul'); // 1 console.log(ul.firstElementChild.textContent); // 5 console.log(ul.lastElementChild.textContent); // 114514 console.log(ul.firstChild); // 1919810 console.log(ul.lastChild); </script>
-
添加节点
创建节点
创建方法:
document.createElement('标签名')
通过createElement
方法创建的元素不属于document
文档,只是创建了个新的元素节点,还需要通过追加节点的方式将其添加到页面上。
了解:还可以通过createTextNode
的方式创建文本节点。
追加节点
-
appendChild
方法-
插入到父元素的最后一个子元素
-
语法
1 2 3 4
// 追加到这个父元素的后面 parentNode.appendChild(child); // parentNode - 父元素 // child 要追加的节点
-
-
insertBefore
方法-
插入到父元素中某个元素的前面
-
语法
1 2 3 4 5
// 插入到某个子元素的前面 parentNode.insertBefore(newNode, referenceNode) // parentNode 父节点 // newNode 要追加的节点 // referenceNode 在这元素的前面
-
案例:
|
|
效果图:
-
补充:
insertAdjacentElement
方法insertAdjacentElement() 方法将一个给定的元素节点插入到相对于被调用的元素的给定的一个位置。
语法:
element.insertAdjacentElement(position, element);
参数:
position
:表示相对于该元素的位置;必须是以下字符串之一:beforebegin
:在该元素本身的前面.afterbegin
:只在该元素当中, 在该元素第一个子孩子前面.beforeend
:只在该元素当中, 在该元素最后一个子孩子后面.afterend
: 在该元素本身的后面.
- 要追加到树中的元素.
所以对于第1点和第2点中提到的
appendChild
方法和insertBefore
方法也可以通过insertAdjacentElement
方法代替,具体如下appendChild
->parentNode.insertAdjacentElement('beforeend',child)
insertBefore
->Node.insertAdjacentElement('beforebegin',child)
所以通过上面的思路可以重写刚才的案例,代码如下:
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
<ul> </ul> <script> let data = [ { id:1, name: 'David' }, { id:2, name: 'Lucy' }, { id:3, name: 'Blue' }, { id:4, name: 'Red' }, { id:5, name: 'Dipper' }, ] let ul = document.querySelector('ul'); data.forEach((item,index)=>{ let newli = document.createElement('li'); newli.innerHTML = ` id:${item.id}<span style="margin-left: 15px"></span>name:${item.name} `; // ul.appendChild(newli); ul.insertAdjacentElement('beforeend',newli); }) let zeroli = document.createElement('li'); zeroli.innerHTML = ` id:0<span style="margin-left: 15px"></span>name:Zero `; // ul.insertBefore(zeroli, ul.firstElementChild); ul.children[0].insertAdjacentElement('beforebegin',zeroli); // ul.children[0].insertAdjacentHTML('beforebegin',`<li>id:0<span style="margin-left: 15px"></span>name:Zero</li>`); </script>
删除节点
removeChild()
方法方法从DOM中删除一个子节点。
使用:
let oldNode = Node.removeChild(child)
child
是要移除的那个子节点.Node
是child
的父节点.oldChild
保存对删除的子节点的引用.oldChild === child
.
案例:
需求进入页面的时候删除一个节点,2s之后将此节点重新添加回页面中
|
|
注意:
- 如果此时不存在父子关系则会删除失败
- 与隐藏节点不同,删除节点是直接从文档流中删掉对应的dom元素
克隆节点
cloneNode()
方法返回调用该方法的节点的一个副本
使用:var dupNode = node.cloneNode(deep);
参数deep
:
- 布尔值为true,表示克隆的时候会包含后代节点一起克隆
- 如果为false,表示克隆的时候不包含后代节点一起克隆
- 默认情况下为false
案例:
要求2s之后复制一个一模一样的ul标签,追加为现在ul的兄弟节点,要求深度克隆
|
|
判断节点是否存在
-
单个元素节点,判定是否为空
-
多个元素集合比如
NodeList
或者HTMLCollection
判断长度是否大于0即可1 2 3 4
let span = document.querySelector('span'); console.log(span !== null); let divs = document.querySelectorAll('div'); console.log(divs.length>0);
获取/修改DOM元素的内容
获取/修改节点内的内容
-
innerText
属性- 将文本的内容添加到标签里面
- 文本里包含的标签内容不会被解析
-
innerHTML
属性-
将文本的内容添加到标签里面
-
文本里包含的标签内容会被解析
-
效果与代码如下所示
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
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <ol> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ol> <script> let ul = document.querySelector('ul'); let ol = document.querySelector('ol'); // 1 2 3 4 5 console.log(ul.innerText); //<li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> console.log(ul.innerHTML); // 1. ul.innerText = '<li><span>1<span></li>'; ol.innerHTML = '<li><span>1<span></li>'; </script>
-
获取/修改包含节点本身的内容
通过outerHTML
可以获取/设置包含节点本身的内容
|
|
获取/修改DOM元素属性
判断是否设置属性
|
|
获取属性
|
|
删除属性
|
|
设置属性
-
通用写法
1
document.getElementById('pattyzzh').setAttribute('class',‘patty’);
-
设置元素常用属性
-
比如通过src更换图片
-
最常见的属性包括:href、title、src等
-
语法:
对象.属性 = 值
1 2 3 4
// 1.获取图片素材 let pic = document.querySelector('img'); // 2.设置图片的src pic.src = `./img/1.png`;
-
-
设置元素样式属性
-
语法:
对象.style.样式属性 = 值
-
修改样式通过style属性引出
-
如果属性有
-
连接符号,需要转为小驼峰命名法 -
赋值的时候不要忘了加
css
单位1 2 3 4 5 6 7 8 9
// 1. 获取元素 let div = document.querySelector('div'); // 2.改变样式 setTimeout(()=>{ // 行内样式 div.style.backgroundColor = 'hotpink'; div.style.width = '400px'; div.style.marginTop = '100px'; }, 1000);
-
-
通过
className
(类名)操作css-
语法:
对象.className = '类名'
-
class
是关键字,所以使用className
代替 -
className
是使用新值替换旧值,如果需要添加一个类,需要保留之前的类名1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
<style> div { width: 300px; height: 300px; background-color: pink; } .active { width: 300px; height: 300px; background-color: hotpink; margin-left: 100px; } </style> <div class="one"></div> <script> // 1. 获取元素 let div = document.querySelector('div'); // 2.改变样式 div.className = 'one active'; </script>
-
-
通过
classList
操作类控制css-
为了解决className容易覆盖多个一起的类名,所以可以通过
classList
方式追加和删除类名 -
语法:
1 2 3 4 5 6
// 追加一个类 元素.classList.add('类名'); // 删除一个类 元素.classList.remove('类名'); // 切换一个类 元素.classList.toggle('类名');
1 2 3 4 5 6 7 8
// 1. 获取元素 let div = document.querySelector('div'); // 2.改变样式 追加 // div.classList.add('active'); // 3.移除 类 // div.classList.remove('active') // 4.切换 类 如果所在的类有 则去掉 ,否则加上 div.classList.toggle('one');
-