1.6. 节点操作
1.6.0. 为什么学节点操作
1.6.1. 节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。
HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
1.6.2. 节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
1.6.3. 父级节点
<div class="demo"> <div class="box"> <span class="erweima">×</span> </div> </div> <script> // 1. 父节点 parentNode var erweima = document.querySelector('.erweima'); // var box = document.querySelector('.box'); // 得到的是离元素最近的父级节点(亲爸爸) 如果找不到父节点就返回为 null console.log(erweima.parentNode); </script>
1.6.4. 子节点
所有子节点
子元素节点
<ul> <li>我是li</li> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ul> <script> // DOM 提供的方法(API)获取 var ul = document.querySelector('ul'); var lis = ul.querySelectorAll('li'); // 1. 子节点 childNodes 所有的子节点 包含 元素节点 文本节点等等 console.log(ul.childNodes); console.log(ul.childNodes[0].nodeType); console.log(ul.childNodes[1].nodeType); // 2. children 获取所有的子元素节点 也是我们实际开发常用的 console.log(ul.children); </script>
第1个子节点
最后1个子节点
第1个子元素节点
最后1个子元素节点
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
<ol> <li>我是li1</li> <li>我是li2</li> <li>我是li3</li> <li>我是li4</li> <li>我是li5</li> </ol> <script> var ol = document.querySelector('ol'); // 1. firstChild 第一个子节点 不管是文本节点还是元素节点 console.log(ol.firstChild); console.log(ol.lastChild); // 2. firstElementChild 返回第一个子元素节点 ie9才支持 console.log(ol.firstElementChild); console.log(ol.lastElementChild); // 3. 实际开发的写法 既没有兼容性问题又返回第一个子元素 console.log(ol.children[0]); console.log(ol.children[ol.children.length - 1]); </script>
1.6.5. 案例:新浪下拉菜单
<script> // 1. 获取元素 var nav = document.querySelector('.nav'); var lis = nav.children; // 得到4个小li // 2.循环注册事件 for (var i = 0; i < lis.length; i++) { lis[i].onmouseover = function() { this.children[1].style.display = 'block'; } lis[i].onmouseout = function() { this.children[1].style.display = 'none'; } } </script>
1.6.6. 兄弟节点
上一个兄弟节点
node.nextSibling // nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
下一个兄弟节点
node.previousSibling // previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
<div>我是div</div> <span>我是span</span> <script> var div = document.querySelector('div'); // 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等 console.log(div.nextSibling); console.log(div.previousSibling); // 2. nextElementSibling 得到下一个兄弟元素节点 console.log(div.nextElementSibling); console.log(div.previousElementSibling); </script>
下一个兄弟元素节点(有兼容性问题)
node.nextElementSibling // nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
上一个兄弟元素节点(有兼容性问题)
node.previousElementSibling //previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。
注意:这两个方法有兼容性问题, IE9 以上才支持。
问:如何解决兄弟节点的兼容性???
function getNextElementSibling(element) { var el = element; while (el = el.nextSibling) { if (el.nodeType === 1) { return el; } } return null; }
1.6.7. 创建节点
document.createElement('tagName') // document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
注意: tagName(标签名称) 指定的 HTML 元素, 元素是根据需求动态生成的,所以称为动态创建节点。
1.6.8. 添加节点
node.appendChild(child) // node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
node.insertBefore(child, 指定元素) // node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
例子练习:
<ul> <li>123</li> </ul> <script> // 1. 创建节点元素节点 var li = document.createElement('li'); // 2. 添加节点 node.appendChild(child) node 父级 child 是子级 后面追加元素 var ul = document.querySelector('ul'); ul.appendChild(li); // 3. 添加节点 node.insertBefore(child, 指定元素); var lili = document.createElement('li'); ul.insertBefore(lili, ul.children[0]); // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素 </script>
1.6.9. 案例:简单版发布留言
<body> <textarea name="" id=""></textarea> <button>发布</button> <ul> </ul> <script> // 1. 获取元素 var btn = document.querySelector('button'); var text = document.querySelector('textarea'); var ul = document.querySelector('ul'); // 2. 注册事件 btn.onclick = function() { if (text.value == '') { alert('您没有输入内容'); return false; } else { // console.log(text.value); // (1) 创建元素 var li = document.createElement('li'); // 先有li 才能赋值 li.innerHTML = text.value; // (2) 添加元素 // ul.appendChild(li); ul.insertBefore(li, ul.children[0]); } } </script> </body>