节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中节点使用 node 来表示。HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点
节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
父级节点
node.parentNode
- parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
- 如果指定的节点没有父节点则返回 null
子节点
//返回所有的子元素节点
parentNode.children
//返回第一个子元素节点,找不到则返回null,IE9以上支持
parentNode.firstElementChild
//返回最后一个子元素节点,找不到则返回null,IE9以上支持
parentNode.lastElementChild
-
parentNode.children
是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。 - 如果想要第一个子元素节点,可以使用
parentNode.chilren[0]
- 如果想要最后一个子元素节点,可以使用
parentNode.chilren[parentNode.chilren.length - 1]
兄弟节点
node.nextSibling
node.previousSibling
- nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null,包含所有的节点。
- previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
node.nextElementSibling
node.previousElementSibling
- nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
- previousElementSibling 返回当前元素上一个兄弟元素节点,找不到则返回null
- 注意:这两个方法有兼容性问题, IE9 以上才支持。
如何解决兼容性问题 ?
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
节点操作
创建节点
document.createElement(‘tagName‘)
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
三种动态创建元素区别
- document.write()
- element.innerHTML
- document.createElement()
区别
-
document.write 是直接将内容写入页面的内容流,此时文档流执行完毕,它会导致页面全部重绘,相同与创建了一个只包含写入内容的新页面
-
innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
-
innerHTML 创建多个元素效率更高,但是采用拼接字符串方式效率低,原因是字符串的不可变性,拼接会不断开辟新空间,采取数组形式效率高
-
createElement() 创建多个元素效率稍低一点点,但是结构更清晰
//数组方式,效率最高
for (var i = 0; i < 1000; i++) {
array.push(‘<div style="width:100px; height:2px; border:1px solid blue;"></div>‘);
}
document.body.innerHTML = array.join(‘‘);
//拼接字符串方式,效率低
var str = ‘‘;
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += ‘<div style="width:100px; height:2px; border:1px solid blue;"></div>‘;
}
//createElement() ,略低于数组方式
for (var i = 0; i < 1000; i++) {
var div = document.createElement(‘div‘);
div.style.width = ‘100px‘;
div.style.height = ‘2px‘;
div.style.border = ‘1px solid red‘;
document.body.appendChild(div);
}
添加节点
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的after 伪元素
node.insertBefore(child, 指定元素)
将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
案例:留言板
<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;
}
</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(‘您没有输入内容‘);
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>
案例分析:
① 点击按钮之后,就动态创建一个li,添加到ul 里面。
② 创建li 的同时,把文本域里面的值通过li.innerHTML 赋值给 li
③ 如果想要新的留言后面显示就用 appendChild 如果想要前面显示就insertBefore
删除节点
node.removeChild(child)
从 DOM 中删除一个子节点,并返回删除的节点。