回顾之前 DOM 的操作都是针对元素节点的属性或文本的,除此之外也有专门针对元素节点本身的操作,如插入、复制、删除、替换等。
插入节点
在已有的 DOM 节点中插入新的 DOM 节点时,需要关注两个关键因素:首先要得到新的 DOM 节点,其次在哪个位置插入这个节点。
如下代码演示:
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
| <body> <h3>插入节点</h3> <p>在现有 dom 结构基础上插入新的元素节点</p> <hr> <!-- 普通盒子 --> <div class="box"></div> <!-- 点击按钮向 box 盒子插入节点 --> <button class="btn">插入节点</button> <script> const btn = document.querySelector('.btn') btn.addEventListener('click', function () { const p = document.createElement('p') p.innerText = '创建的新的p标签' p.className = 'info' const p2 = document.querySelector('p').cloneNode(true) p2.style.color = 'red'
document.querySelector('.box').appendChild(p) document.querySelector('.box').appendChild(p2) }) </script> </body>
|
结论:
createElement 动态创建任意 DOM 节点
cloneNode 复制现有的 DOM 节点,传入参数 true 会复制所有子节点
appendChild 在末尾(结束标签前)插入节点
再来看另一种情形的代码演示:
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
| <body> <h3>插入节点</h3> <p>在现有 dom 结构基础上插入新的元素节点</p> <hr> <button class="btn1">在任意节点前插入</button> <ul> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul> <script> const btn1 = document.querySelector('.btn1') btn1.addEventListener('click', function () {
const relative = document.querySelector('li:nth-child(2)')
const li1 = document.createElement('li') li1.style.color = 'red' li1.innerText = 'Web APIs'
const li2 = document.querySelector('li:first-child').cloneNode(true) li2.style.color = 'blue'
document.querySelector('ul').insertBefore(li1, relative) document.querySelector('ul').insertBefore(li2, relative) }) </script> </body>
|
结论:
createElement 动态创建任意 DOM 节点
cloneNode 复制现有的 DOM 节点,传入参数 true 会复制所有子节点
insertBefore 在父节点中任意子节点之前插入新节点
删除节点
删除现有的 DOM 节点,也需要关注两个因素:首先由父节点删除子节点,其次是要删除哪个子节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <body> <!-- 点击按钮删除节点 --> <button>删除节点</button> <ul> <li>HTML</li> <li>CSS</li> <li>Web APIs</li> </ul>
<script> const btn = document.querySelector('button') btn.addEventListener('click', function () { let ul = document.querySelector('ul') let lis = document.querySelectorAll('li')
ul.removeChild(lis[0]) }) </script> </body>
|
结论:removeChild 删除节点时一定是由父子关系。
查找节点
DOM 树中的任意节点都不是孤立存在的,它们要么是父子关系,要么是兄弟关系,不仅如此,我们可以依据节点之间的关系查找节点。
父子关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <body> <button class="btn1">所有的子节点</button> <!-- 获取 ul 的子节点 --> <ul> <li>HTML</li> <li>CSS</li> <li>JavaScript 基础</li> <li>Web APIs</li> </ul> <script> const btn1 = document.querySelector('.btn1') btn1.addEventListener('click', function () { const ul = document.querySelector('ul')
console.log(ul.childNodes) console.log(ul.children) }) </script> </body>
|
结论:
childNodes 获取全部的子节点,回车换行会被认为是空白文本节点
children 只获取元素类型节点
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
| <body> <table> <tr> <td width="60">序号</td> <td>课程名</td> <td>难度</td> <td width="80">操作</td> </tr> <tr> <td>1</td> <td><span>HTML</span></td> <td>初级</td> <td><button>变色</button></td> </tr> <tr> <td>2</td> <td><span>CSS</span></td> <td>初级</td> <td><button>变色</button></td> </tr> <tr> <td>3</td> <td><span>Web APIs</span></td> <td>中级</td> <td><button>变色</button></td> </tr> </table> <script> const buttons = document.querySelectorAll('table button') for(let i = 0; i < buttons.length; i++) { buttons[i].addEventListener('click', function () { this.parentNode.parentNode.style.color = 'red' }) } </script> </body>
|
结论:parentNode 获取父节点,以相对位置查找节点,实际应用中非常灵活。
兄弟关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <body> <ul> <li>HTML</li> <li>CSS</li> <li>JavaScript 基础</li> <li>Web APIs</li> </ul> <script> const lis = document.querySelectorAll('ul li')
for(let i = 0; i < lis.length; i++) { lis[i].addEventListener('click', function () { console.log(this.previousSibling) console.log(this.nextSibling) }) } </script> </body>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> const li2 = document.querySelector('ul li:nth-child(2)') console.log(li2.previousElementSibling) console.log(li2.nextElementSibling) </script> </body>
|
结论:
previousSibling 获取前一个节点,回车换行会被认为是空白文本节点
nextSibling 获取后一个节点,回车换行会被认为是空白文本节点
previousElementSibling 获取前一个节点,以相对位置查找节点,实际应用中非常灵活。
nextElementSibling 获取后一个节点,以相对位置查找节点,实际应用中非常灵活。