前面学习了基本的元素的获取,属性样式的设置等等内容。现在学习新的知识点---节点。
一、为什么学节点操作
首先明确,节点操作的使用目的是什么?节点操作的意义还是获取元素对象。
以前我们获取的方法,是直接使用DOM的内置方法直接抓取对应的类名、标签类型的对象。没有逻辑性。
节点操作更讲究逻辑性,划分父、子、兄弟节点,来寻找选中对象。
所以什么时候用?当然是有具体的父子级关系的时候使用最方便,不必再去抓取父级标签对象。
二、 节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。 HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
注意:标签、属性、文本(含文字、空格、换行等)、注释都算是节点。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个 基本属性。
元素节点 nodeType 为 1 ;属性节点 nodeType 为 2 ;文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等);
我们可以看出,除去属性和文本之外,DOM树的主干还是元素。
三、 节点层级
3.1 父级节点
node.parentNode
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点。
如果指定的节点没有父节点则返回 null。
3.2 子节点
parentNode.childNodes(标准)
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes。
parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返 回 (这个是我们重点掌握的)。
同时,可以获取第一个和最后一个子节点。
注意:是所有节点,而不是元素!!!!
//firstChild 返回第一个子节点,找不到则返回null。
parentNode.firstChild
//astChild 返回最后一个子节点,找不到则返回null。
parentNode.lastChild
所以使用一下方法获取子元素:
parentNode.firstElementChild
//firstElementChild 返回第一个子元素节点,找不到则返回null。
parentNode.lastElementChild
//lastElementChild 返回最后一个子元素节点,找不到则返回null。
3.3 兄弟节点
node.nextSibling
//nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
node.previousSibling
//previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
四、 节点创建
document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在, 是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
五、节点添加
何时会用到添加节点?一般是给父节点添加子节点。
1. node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
2. node.insertBefore(child, 指定元素)
ul.insertBefore(li, ul.children[0]);
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
六、 节点删除
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
七、 节点复制
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点 5.6 复制节点(克隆节点)
注意:
1. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
2. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<ul>
<li>1111</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
var li = ul.children[0].cloneNode();
ul.appendChild(li);
// 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
</body>
</html>
八、综合案例1---留言板
思路分析:1、需要获取按钮对象、textarea对象、ul对象、链接a对象。2、对按钮绑定事件,每次点击发布,创建一个新的 li 对象,存入textarea对象的内容,并增加一个链接后面。同时使用inertbefore 将新的li 插入到ul.children的第一个之前 。3、选出所有的a,如果a被点击了,则从ul中removeChild(a对象.parentNode),注意a对象.parentNode就是点击的a所在的li。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding: 100px;
}
textarea {
width: 200px;
height: 100px;
border: 1px solid pink;
outline: none;
resize: none;
}
ul {
margin-top: 50px;
}
li {
width: 300px;
padding: 5px;
background-color: rgb(245, 209, 243);
color: red;
font-size: 14px;
margin: 15px 0;
}
li a {
float: right;
}
</style>
</head>
<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('您未输入内容,无法发布');
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
// href = 'javascript:void(0)' 或者 href = 'javascript:;'防止跳转
li.innerHTML = text.value + "<a href='javascript:void(0)'>删除</a>";
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
// (3) 删除元素 删除的是当前链接的li 它的父亲
var as = document.querySelectorAll('a');
for (let i = 0; i < as.length; i++) {
as[i].onclick = function () {
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
九、 综合案例2 --- 生成动态表格
案例分析:1、用thead装表头,用tbody装信息。2、创建datas以数组的形式保存数据。3、获取tbody对象。4、每一次循环,创建新的行tr,并插入tbody。5、再创建新的内部循环,读取datas【】内部的内容,每存在一个内容,创建一个新的td,去存放,插入tr。4、捕获删除链接,如果点击了,就获取该链接的付清节点,然后从tbody中删除。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
</head>
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 1.先去准备好学生的数据
var datas = [{
name: '魏璎珞',
subject: 'JavaScript',
score: 100
}, {
name: '弘历',
subject: 'JavaScript',
score: 98
}, {
name: '傅恒',
subject: 'JavaScript',
score: 99
}, {
name: '明玉',
subject: 'JavaScript',
score: 88
}, {
name: '大猪蹄子',
subject: 'JavaScript',
score: 0
}];
// 2. 往tbody 里面创建行: 有几个人(通过数组的长度)我们就创建几行
var tbody = document.querySelector('tbody');
for (let i = 0; i < datas.length; i++) {
var tr = document.createElement('tr');
tbody.appendChild(tr);
for (let k in datas[i]) {
var td = document.createElement('td');
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
var td = document.createElement('td');
td.innerHTML = "<a href='javascript:;'>删除</a>"
tr.appendChild(td);
}
// 4. 删除操作 开始
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
tbody.removeChild(this.parentNode.parentNode);
}
}
// for(var k in obj) {
// k 得到的是属性名
// obj[k] 得到是属性值
// }
</script>
</body>
</html>