5 节点操作
5.1 为什么学习节点操作
5.2 节点概述
一般情况下,节点至少拥有节点类型(nodeType)、节点名称(nodeName)、节点值(nodeValue)这三个基本属性
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="box">
<span class="erweima">x</span>
</div>
<script>
var box = document.querySelector('.box');
console.dir(box); //可以通过这个方式查看节点的属性
</script>
</body>
查看部分属性:
- 元素节点的nodeType为1(常用)
- 属性节点的nodeType为2
- 文本节点的nodeType为3(包含文字空格换行等)
5.3 节点层级
父级节点
node.parentNode
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="demo">
<div class="box">
<span class="erweima">x</span>
</div>
</div>
<script>
//获取box和erweima这两个盒子
//过去的做法
// var erweima = document.querySelector('.erwima');
// var box = document.querySelector('.box');
//1. 父节点parentNode 现在的做法
var erweima = document.querySelector('.erweima');
console.log(erweima.parentNode); //得到的是距离元素erweima最近的父级节点box,如果找不到其父节点就返回为null
</script>
</body>
子节点
- 标准:
parentNode.childNodes
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ol>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ol>
<div class="demo">
<div class="box">
<span class="erweima"></span>
</div>
</div>
<script>
//获取ul里面的li
//过去的方法
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
//现在的方法
//1. 子节点 返回包含指定节点的字节的的集合,该集合为即时更新的集合
console.log(ul.childNodes); //NodeList(9)?[text, li, text, li, text, li, text, li, text] 返回值里包含了所有的节点包括元素节点、文本节点等 中间有5个换行,所以有5个文本节点text
console.log(ul.childNodes[0].nodeType); //3 文本节点的nodeType的属性是3
console.log(ul.childNodes[1].nodeType); //1 元素节点的nodeType的属性是1
//为了获得其中的元素节点需要专门处理(所以一般不提倡用childNodes)
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType == 1) {
console.log(ul.childNodes[i]);
}
}
</script>
</body>
- 非标准:
parentNode.children//可以得到所有的子元素节点 是一个只读属性 返回一个伪数组
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ol>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ol>
<div class="demo">
<div class="box">
<span class="erweima"></span>
</div>
</div>
<script>
//获取ul里面的li
//过去的方法
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
//现在的方法
//1. 子节点 返回包含指定节点的字节的的集合,该集合为即时更新的集合
console.log(ul.childNodes); //NodeList(9)?[text, li, text, li, text, li, text, li, text] 返回值里包含了所有的节点包括元素节点、文本节点等 中间有5个换行,所以有5个文本节点text
console.log(ul.childNodes[0].nodeType); //3 文本节点的nodeType的属性是3
console.log(ul.childNodes[1].nodeType); //1 元素节点的nodeType的属性是1
//为了获得其中的元素节点需要专门处理(所以一般不提倡用childNodes)
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType == 1) {
console.log(ul.childNodes[i]);
}
}
//2. 获取所有的子元素节点
console.log(ul.children); //HTMLCollection(4)?[li, li, li, li]
</script>
</body>
子节点的相关操作:获取第一个子元素和最后一个子元素
parentNode.firstChild //返回第一个子节点,找不到则返回null。同样也是包含所有的节点
parentNode.lastChild //返回最后一个子节点,找不到则返回null。同样也是包含所有的节点
parentNode.firstElementChild //返回第一个子节点,找不到则返回null。只包含元素节点
parentNode.lastElementChild //返回最后一个子节点,找不到则返回null。只包含元素节点
注意:后两个方法有兼容性问题,ie9以上才支持
<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
</ol>
<script>
var ol = document.querySelector('ol');
//1. 不仅仅包含元素节点
console.log(ol.firstChild); //#text 文本节点
console.log(ol.lastChild); //#text 文本节点
//2. 兼容新问题
console.log(ol.firstElementChild); //<li>我是li1</li>
console.log(ol.lastElementChild); //<li>我是li4</li>
//3. 实际开发 既没有兼容性问题又返回第一个子元素
console.log(ol.children[0]); //<li>我是li1</li>
console.log(ol.children[ol.children.length - 1]); //<li>我是li4</li>
</script>
</body>
案例:下拉菜单
- 导航栏里面的li都要有鼠标经过的效果,所以需要循环注册鼠标事件
- 核心原理:当鼠标经过li里面的第二个孩子(ul)显示,当鼠标离开,则ul隐藏。
<body>
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<script>
//1. 获取元素
var nav = document.querySelector('.nav');
var lis = nav.querySelectorAll('li'); //得到4个小li
//2. 循环注册事件
for (var i = 0; i < lis.length - 1; i++) {
lis[i].onmouseover = function() {
this.children[1].style.display = 'block';
}
lis[i].onmouseout = function() {
this.children[1].style.display = 'none';
}
}
</script>
</body>
样式内容省略
兄弟节点
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
//1. node.nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null。包含所有节点
console.log(div.nextSibling); //#text
//2. node.previousSibling 返回当前元素的上一个兄弟节点,找不到则返回null。包含所有节点
console.log(div.previousSibling); //#text
//3. node.nextElementSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。
console.log(div.nextElementSibling); //<span>我是span</span>
//4. node.previousElementSibling 返回当前元素的上一个兄弟元素节点,找不到则返回null。
console.log(div.previousElementSibling); //null 因为div上面没有兄弟了
//后两个方法依然有兼容性问题,ie9以上才支持
//解决方法:自己封装一个函数(了解)
function getnextElementSibling(element){
var el = element;
while(el = el.nextSibling) {
if(el.nodeType == 1) {
return el;
}
}
return null;
}
</script>
</body>
5.4 创建节点 和添加节点
- 创建
document.creatElement('tagName')
document.creatElement()方法创建由tagName指定的HTML元素。因为这些元素原先不存在,是我们根据需求动态生成的,所以我们也称为动态创建元素节点。
- 添加
node.appendChild(child)
node.appendChild()方法将一个节点添加到指定父节点的子节点列表的末尾。类似于css元素里的after伪元素。
node.insertBefore(child,指定元素)
node.insertBefore()方法将一个节点添加到父节点指定子节点前面。类似于css里面的before伪元素
<body>
<ul>
<li>123</li>
</ul>
<script>
//在ul里动态地再创建一个li
//1. 创建元素节点
var li = document.createElement('li');
//2. 添加节点 node.appendChild(child) node是父级 child是子级 在后面追加元素
var ul = document.querySelector('ul');
ul.appendChild(li);
//1. 创建元素节点
var lili = document.createElement('li');
//3. 添加节点node.insertBefore(child,指定元素)
ul.insertBefore(lili, ul.children[0]);
</script>
</body>
案例:简单版发布留言案例
- 思路: 当点击按钮之后就动态创建一个li,之后再把li创建到ul之中就可以了
- 在创建li的同时,把文本域里面的值通过li.innerHTML赋值给li
- 如果想要新的留言后面显示就用appendChild,如果想要前面显示就用insertBefore
<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 {
//(1)创建元素
var li = document.createElement('li');
//给li赋值
li.innerHTML = text.value;
//(2)添加元素
// ul.appendChild(li);新留言在最后
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
样式省略