【第五部分 | JS WebAPI】3:DOM 节点操作

太过爱你忘了你带给我的痛 2023-09-23 16:06 203阅读 0赞

目录

| 节点操作

1-1 概述

2-1 获取父节点

3-1 获取子节点(获取所有子对象 不推荐)

3-2 获取子节点(获取所有子【元素节点】)

3-3 获取首尾子节点

4-1 获取兄弟节点

5-1 动态创建、添加节点

5-2 案例:评论区

5-4 删除节点

5-5 复制节点

| 综合案例:动态生成表格

| 三种动态创建元素的区别

| 总结


| 节点操作

1-1 概述

什么是节点?

  • 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。我们常用的是元素节点
  • HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以 创建或删除。
  • b399c4d76c094bd79aa648e41569b091.png
  • 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个 基本属性。
  • 我们在实际开发中,节点操作主要操作的是元素节点

什么是节点操作?

00fb1d14ce5d476eb4b1f7158d5c8805.png

代码示例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div>
  11. <span></span>
  12. </div>
  13. <script>
  14. // 如果以前想得到div和span元素,需要进行两步
  15. var divObj = document.getElementsByTagName('div');
  16. var spanObj = document.getElementsByTagName('span');
  17. // 而我们若使用节点操作来获取父元素,则只需要获取某一个元素对象,然后根据这个元素对象和其它元素对象的层级关系,使用对应的函数即可
  18. // span是div的父节点。我们得到了span,则只需要操作这个节点,使用parentNode就可以获取其父节点对象div了
  19. var spanObj2 = document.getElementsByTagName('span');
  20. divObj2 = spanObj2[0].parentNode;
  21. console.log(divObj2); //div
  22. </script>
  23. </body>
  24. </html>

2-1 获取父节点

eae66825092842308392ba5b88ebb44d.png


3-1 获取子节点(获取所有子对象 不推荐)

9179e5cf3d0347f8a8055c66de513103.png

子元素的标签、换行符会被认为是节点。 如下列代码,若使用

var ul = document.getElementsByTags(‘ul’);

var lis = ul.childNodes;

代码,则会获得的不仅仅是一个含有2个li的元素对象伪数组,而是一个含有5个元素对象的伪数组

具体原因如下

  1. <ul>(换行 第一个节点)
  2. <li(标签,第二个节点)>XXX</li>(换行,第三个节点)
  3. <li(标签,第四个节点)>XXX</li>(换行,第五个节点)
  4. </ul>
  • 综上,因为返回值里面包含了所有的子节点,包括元素节点,文本节点等。 如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes

3-2 获取子节点(获取所有子【元素节点】)

  1. parentNode.children

66a128da669c4f9cbed9b441d6e7473a.png

代码示例(childNode 和 children 的对比)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div>
  11. <span></span>
  12. <span></span>
  13. <span></span>
  14. <span></span>
  15. </div>
  16. <script>
  17. var divObj = document.querySelector('div');
  18. var children1 = divObj.childNodes;
  19. var children2 = divObj.children;
  20. var str1 = '';
  21. var str2 = '';
  22. for(var i=0 ; i<children1.length ; i++) {
  23. str1 += children1[i];
  24. }
  25. for(var i=0 ; i<children2.length ; i++) {
  26. str2 += children2[i];
  27. }
  28. console.log(str1); //[object Text][object HTMLSpanElement][object Text][object HTMLSpanElement][object Text][object HTMLSpanElement][object Text][object HTMLSpanElement][object Text]
  29. console.log(str2); //[object HTMLSpanElement][object HTMLSpanElement][object HTMLSpanElement][object HTMLSpanElement]
  30. </script>
  31. </body>
  32. </html>

3-3 获取首尾子节点

注意:firstChild得到的 该子节点包含“换行符等非元素节点”

a1e3118ed84e42c69bfa7da846077d1d.png

下列两个方法可以获取的是首尾子【元素】节点

e80285ea9b2a47f7936f4938310b00b1.png

实际开发中,如何用兼容IE9以下版本浏览器的方法得到 firstElementChild 和 lastElementChild ?

实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

解决方案:

1.如果想要第一个子元素节点,可以使用 parentNode.chilren[0]

2.如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]


4-1 获取兄弟节点

注意:该方法得到的 兄弟节点包含“换行符等非元素节点”

  1. node.nextSibling //返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
  2. node.previousSibling // 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。

下列两个方法可以获取的是兄弟子【元素】节点

  1. node.nextElementSibling //返回当前元素下一个兄弟元素节点,找不到则返回null。
  2. node.previousElementSibling //g 返回当前元素上一个兄弟节点,找不到则返回null。

可以自己封装一个兼容IE9以下浏览器的获取兄弟子【元素】节点的函数

  1. function getNextElementSibling(element) {
  2. var el = element;
  3. while (el = el.nextSibling) {
  4. if (el.nodeType === 1) {
  5. return el;
  6. }
  7. }
  8. return null;
  9. }

5-1 动态创建、添加节点

  • 使用场景:如想给 ul 中动态地添加 li

60dbfa9490a94a1b9f11516faf5d3370.png

代码示例

基本步骤:获取父节点元素 → 创建要插入的元素 → 插入元素

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. </ul>
  12. <script>
  13. // 动态创建元素节点
  14. var liElement = document.createElement('li');
  15. // 把创建的元素节点加入(获取父节点 → 添加子节点)
  16. var ulNode = document.querySelector('ul');
  17. ulNode.appendChild(liElement);
  18. </script>
  19. </body>
  20. </html>

5-2 案例:评论区

核心思路︰点击按钮之后,就动态创建一个li,添加到ul里面。创建li的同时,把文本域里面的值通过li.innerHTML赋值给li

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0;
  12. }
  13. li {
  14. list-style: none;
  15. }
  16. textarea{
  17. display: block;
  18. resize:none; /* 取消拖拽 */
  19. outline: none;/* 取消选中高亮 */
  20. height: 200px;
  21. width: 500px;
  22. margin: 100px auto;
  23. margin-bottom: 30px;
  24. background-color: aliceblue;
  25. padding: 10px;
  26. font-family: 'Microsoft YaHei';
  27. font-size: 20px;
  28. }
  29. button {
  30. display: block;
  31. background-color: lightskyblue;
  32. width: 100px;
  33. height: 40px;
  34. margin: 0 auto;
  35. }
  36. ul {
  37. width: 500px;
  38. margin: 40px auto;
  39. background-color: lightgoldenrodyellow;
  40. }
  41. li {
  42. width: 500px;
  43. margin: 5px auto;
  44. height: 30px;
  45. border-bottom: 1px solid grey;
  46. }
  47. </style>
  48. </head>
  49. <body>
  50. <textarea placeholder="输入评论" name="comment"></textarea>
  51. <button>发布</button>
  52. <ul>
  53. </ul>
  54. <!-- 点击按钮,获取文本域,然后添加li -->
  55. <script>
  56. var btn = document.querySelector('button');
  57. var text = document.querySelector('textarea');
  58. btn.onclick = function(){
  59. // 获取文本域文本
  60. var textContent = text.value;
  61. //创建li节点
  62. var newLi = document.createElement('li');
  63. //添加li节点
  64. var ul = document.querySelector('ul');
  65. ul.appendChild(newLi);
  66. // 向li节点中添加内容 innerHTML
  67. newLi.innerHTML = textContent;
  68. // 清空文本
  69. text.value = '';
  70. }
  71. </script>
  72. </body>
  73. </html>

5-4 删除节点

c1cd795fc6bb471a9898b1ecfdcaefe8.png

代码示例

896153a458a343e0bf8ee99c4ff78d12.png


5-5 复制节点

f6f6546e71244f06a3dc509c67c0b279.png

代码示例

7b32ca849d8542d293cef42cf5d95167.png


| 综合案例:动态生成表格

目前还没学习Ajax,无法动态通过数据库获取数据。因此我们把数据写在对象中

注意体会上述知识的综合使用:

  • CSS 和 Html的知识
  • 数组存放对象
  • 循环创建事件
  • 如何在table的tbody中插入行、在行中插入列
  • 注意删除按钮的书写 要使用innerHTML方法以渲染html标签
  • 注意删除的时候,删除的是 相对于a 的父亲(tr)的父亲(td),即删除行的那个元素节点。

示例代码:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <style>
  9. table {
  10. width: 500px;
  11. margin: 100px auto;
  12. border-collapse: collapse;
  13. text-align: center;
  14. }
  15. td,
  16. th {
  17. border: 1px solid #333;
  18. }
  19. thead tr {
  20. height: 40px;
  21. background-color: #ccc;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <table cellspacing="0">
  27. <thead>
  28. <tr>
  29. <th>姓名</th>
  30. <th>科目</th>
  31. <th>成绩</th>
  32. <th>操作</th>
  33. </tr>
  34. </thead>
  35. <tbody>
  36. </tbody>
  37. </table>
  38. <script>
  39. // 1.先去准备好学生的数据
  40. var datas = [{
  41. name: '魏璎珞',
  42. subject: 'JavaScript',
  43. score: 100
  44. }, {
  45. name: '弘历',
  46. subject: 'JavaScript',
  47. score: 98
  48. }, {
  49. name: '傅恒',
  50. subject: 'JavaScript',
  51. score: 99
  52. }, {
  53. name: '明玉',
  54. subject: 'JavaScript',
  55. score: 88
  56. }, {
  57. name: '大猪蹄子',
  58. subject: 'JavaScript',
  59. score: 0
  60. }];
  61. // 2. 往tbody 里面创建行: 有几个人(通过数组的长度)我们就创建几行
  62. var tbody = document.querySelector('tbody');
  63. for (var i = 0; i < datas.length; i++) { // 外面的for循环管行 tr
  64. // 1. 创建 tr行
  65. var tr = document.createElement('tr');
  66. tbody.appendChild(tr);
  67. // 2. 行里面创建单元格(跟数据有关系的3个单元格) td 单元格的数量取决于每个对象里面的属性个数 for循环遍历对象 datas[i]
  68. for (var k in datas[i]) { // 里面的for循环管列 td
  69. // 创建单元格
  70. var td = document.createElement('td');
  71. // 把对象里面的属性值 datas[i][k] 给 td
  72. // console.log(datas[i][k]);
  73. td.innerHTML = datas[i][k];
  74. tr.appendChild(td);
  75. }
  76. // 3. 创建有删除2个字的单元格
  77. var td = document.createElement('td');
  78. td.innerHTML = '<a href="javascript:;">删除 </a>';
  79. tr.appendChild(td);
  80. }
  81. // 4. 删除操作 开始
  82. var as = document.querySelectorAll('a');
  83. for (var i = 0; i < as.length; i++) {
  84. as[i].onclick = function() {
  85. // 点击a 删除 当前a 所在的行(链接的爸爸的爸爸) a的爸爸是tr,tr的爸爸是td,因此删除的是td。注意使用的是this
  86. tbody.removeChild(this.parentNode.parentNode)
  87. }
  88. }
  89. // for(var k in obj) {
  90. // k 得到的是属性名
  91. // obj[k] 得到是属性值
  92. // }
  93. </script>
  94. </body>
  95. </html>

| 三种动态创建元素的区别

49f5d8c7cae641ce8cc8e1e8fdd35c81.png

| 总结

b7408fdc45184a23809ebef0b3660209.png

098774d07ad0407491ff8bad7f661a4c.png

e3f4c30b8e7f4a2baa483202a63246a0.png

f21f38219e4b44e5a264e495b1c4eb41.png

发表评论

表情:
评论列表 (有 0 条评论,203人围观)

还没有评论,来说两句吧...

相关阅读