1.节点介绍
为什么引入节点?
- 利用DOM提供的多种获取方法
- 缺点:繁琐+逻辑性不强
- 需要重复获取元素
- 利用节点获取元素
- 利用父子兄弟节点关系获取元素
- 缺点:兼容性差
2. 节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示HTML DOM树中的所有节点均可以通过JavaScript进行访问,所有HTML元素均可以被修改,也可以创建或删除
- 所有内容是节点(用node表示)
- 元素也是节点:元素节点
- 文档节点
- 属性节点
- 文本节点(包括空格)
-
实际操作中主要获取元素节点(然后就可以引出兄弟父子节点)
3. 节点类型判断
node.nodeType
- 元素节点:nodeType 为 1
- 属性节点:nodeType 为 2
- 文本节点:nodeType 为 3(文字节点包含文字、空格、换行等)
4. 父级节点
node.parentNode
5. 子级节点
-
获取到元素节点+文本节点方式
-
以伪数组形式获得元素节点
parentNode.childNodes 标准子节点获取方式
parentNode.childNodes[index] 获取指定下标子节点
2.获得元素子节点方式
-
以伪数组形式获得元素节点
parentNode.children 非标准子节点获取方式
-
直接获取指定元素节点 (适合开发使用)
- ol.children[0]
- ol.children[ol.children.length - 1]
-
也许会获得文本元素
- parentNode.firstchild
- parentNode.lastchild
-
查找子节点元素
parentNode.firstElementchild 注意受兼容ie9
6. 案例-下拉菜单(使用子节点操作)
<script>
// 1.获取元素
var nav = document.querySelector(".nav");
var lis = nav.children; //获取四个小li
// 根据循环注册事件
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function () {
// li里面的第一个元素ul(包裹其他元素)就是第一个元素节点显示出来
this.children[1].style.display = "block";
};
lis[i].onmouseout = function () {
this.children[1].style.display = "none";
};
}
</script>
-
执行效果:鼠标移动到哪个ul上就会显示当前的ul,但是如果从当前ul移除就会消失
-
代码解析:
- 布置静态页面
- 首先获取到元素大盒子+大盒子下的多个小盒子
- 遍历小盒子
- 当前小盒子设置鼠标移动事件
- 移动上去:当前小盒子(不包括a链接)的元素显示
- 移动出去:当前小盒子(不包括a链接)的元素隐藏
7. 兄弟节点
- node.nextSibling 下一个兄弟节点
- node.previousSibling 上一个兄弟节点
- 缺点:容易获取到文本元素节点(介绍点属性3)
直接封装一个兄弟元素节点获取方式
function getNextElementSibling(element) {
var el = element;
while ((el = el.nextSibling)) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
- node.nextElementSibling 下一个兄弟元素节点
- node.previousElementSibling 上一个兄弟元素节点
- 如果没有找到兄弟元素节点则返回null
8. 创建节点+添加节点
- 相对于整个文档创建节点: document.createElement('tagName')
- 添加到指定父节点下的位置
- 父node.appendChild(child) 添加到指定父节点后面
- 父node.insertBefore(child,指定节点) 添加子节点到指定父节点的子节点前面
<body>
<ul>
<li>123</li>
</ul>
<script>
// 1.在整个文档页面创建节点:元素节点
var li = document.createElement("li");
// 2.把节点放到父节点最后面
var ul = document.querySelector("ul");
ul.appendChild(li); //追加元素 类似于push
// 3.把创建节点放在父节点指定元素前面
// 创建节点
var lili = document.createElement("li");
ul.insertBefore(lili, ul.children[0]);
//4.想要添加一个新的元素:创建元素+添加元素
</script>
</body>
9. 案例-发布评论
<body>
<div class="box">
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
</div>
<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
ul.insertBefore(li, ul.children[0]);
}
};
</script>
</body>
-
执行效果:文本内容中输入内容点击发布就会出现下方创建并添加节点
-
代码解析:
- 布置静态页面
- 获取元素
- 按钮设置点击事件
- 判断
- 如果当前文本框没有内容则弹窗:没有输入文字
- 否则创建节点
- 创建好节点
- 修改当前节点内容
- 并把当前节点添加到ul的最前面
10. 删除节点
- 父node.removeChild(child)
- 删除父节点的第几个子节点
<body>
<button>删除</button>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
// 1. 获取元素
var ul = document.querySelector("ul");
var btn = document.querySelector("button");
// 2.删除节点:删除父节点的第几个节点
// ul.removeChild(ul.children[0]);
// 3.点击按钮以此删除
btn.onclick = function () {
if (ul.children.length == 0) {
btn.disabled = true; //禁用按钮属性
} else {
ul.removeChild(ul.children[0]);
}
};
</script>
11.案例-删除节点
<body>
<div class="box">
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
</div>
<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才能赋值+删除链接
// 注意a的链接地址更换之后才不会跳转出现乱七八糟的
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
// 2.添加得ul
ul.insertBefore(li, ul.children[0]);
//3.删除事件
var as = document.querySelectorAll("a");
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
//删除事件(删除a节点的父节点li)
ul.removeChild(this.parentNode);
};
}
}
};
</script>
</body>
-
实现效果:在添加节点的基础上并添加一个删除链接(点击删除就会删除父节点)
-
代码解析
- 布置静态页面
- 获取元素
- 设置按钮点击事件
- 判断
- 如果当前文本框没有内容则弹窗:没有输入文字
- 否则创建节点li
- 创建好节点
- 修改当前节点内容+标签a标签包括删除内容
- 并把当前节点添加到ul的最前面
- 设置删除事件
- 获取所有a元素
- 遍历a并给当前a标签设置点击事件
- 父元素删除当前子节点的父节点
12.克隆节点
node.clonNode()
-
如果参数为空或为false,则是浅拷贝,,即克隆隆赋值节点本身,不克隆里面子节点(内容。)
-
如果参数为true:代表克隆或者赋值里面所有内容(深拷贝)
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector("ul");
// 1.克隆
// node.colonNode():参数为空或者false,就是浅拷贝,只复制标签不赋值内容
// 如果里面是true就是深拷贝:赋值或者克隆所有内容
var cl_ul = ul.children[0].cloneNode(true);
// 2.插入节点
ul.appendChild(cl_ul);
</script>
</body>
13. 案例-动态生成表格
<script>
// 1.先准备数据
var dates = [
{
name: "刘某",
subject: "JacaScrit",
score: 100,
},
{
name: "任某",
subject: "JacaScrit",
score: 90,
},
{
name: "张某",
subject: "JacaScrit",
score: 80,
},
{
name: "屠某",
subject: "JacaScrit",
score: 70,
},
{
name: "张某",
subject: "JacaScrit",
score: 70,
},
];
// 2.往tbody创建行:通过数组长度
var tbody = document.querySelector("tbody");
for (var i = 0; i < dates.length; i++) {
// 创建行
var tr = document.createElement("tr");
// 插入
tbody.appendChild(tr);
// 创建td:数值取决于对象个数
for (var k in dates[i]) {
// k得到属性名
// obj[k]:得到属性值
var td = document.createElement("td");
// 创建td的同时把属性值给td
td.innerHTML = dates[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 () {
// 点击a删除所在行:node.removeChild(child)
//a是td的孩子,td又是tr的孩子
tbody.removeChild(this.parentNode.parentNode);
};
}
</script>
-
执行效果:根据程序对象添加多个表格行并可以点击删除当前一行
-
代码解析
- 布置静态页面(只有当前页面的表头)给一个空的表格内容
- 创建一个对象:所有类都设置好
- 获取元素tbody
- 遍历对象
- 根据对象数:创建行并插入到tbody的后面
- 遍历当前对象
- 创建td并添加对象内容给当前元素节点
- 把创建的节点插入到行的最后面
- 单独创建一个单元格
- 把删除链接添加给单元格
- 并把单元格添加到行的最后面
- 删除操作
- 获取所有标签a
- 遍历所有标签a
- 设置当前标签a点击事件
- 父节点删除当前子节点的父节点的父节点
14. 三种创建元素节点
document.write(’标签+元素内容‘)
缺点:页面重置,原先创建的元素就会消失
var btn = document.querySelector("button");
btn.onclick = function () {
// 会重新创建页面:原先的页面就没了
document.write("<div>123</div>");
};
- element.innerHTML = ’标签+元素内容‘
var inner = document.querySelector(".inner");
// 拼接字符串 效率比较慢
for (var i = 0; i <= 100; i++) {
inner.innerHTML += '<a href="#">百度</a>';
}
- document.creatElement('节点')
- 注意需要添加到父元素指定位置
var creat = document.querySelector(".creat");
for (var i = 0; i <= 100; i++) {
var a = document.createElement("a");
creat.appendChild(a);
}
15. 比较创建节点最优性
- 最优创建节点:测试获取两个不同时间戳并进行计算添加后的时间差
- 测试:根据push到数组并转成字符串join
<script>
function fn() {
var dl = +new Date();
// 初始化空数组
var array = [];
// 依次在数组后面push一个元素(带有样式)
for (var i = 0; i < 1000; i++) {
array.push(
'<div style="width: 100px;height: 2px;border: 1px solid #000;"></div>'
);
}
// 数组转化成字符串
document.body.innerHTML = array.join("");
var d2 = +new Date();
console.log(d2 - dl);
}
fn();
</script>
- 较快创建节点:
- 测试:
- 遍历:直接创建节点并直接添加属性最后添加节点到父级节点
<script>
function fn() {
// 获取未执行前时间
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
// 利用creatElement创建元素并且添加好样式
var div = document.createElement("div");
div.style.width = "100px";
div.style.height = "2px";
div.style.border = "1px solid red";
// 依次添加到body里面
document.body.appendChild(div);
}
// 获取执行后时间
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
- 最慢节点创建
- 测试:直接使用innerHTML创建一个带有属性的节点
<script> function fn() { // 获得当前时间 var d1 = +new Date(); var str = ""; for (var i = 0; i < 1000; i++) { // 利用html创建元素并且添加好样式 document.body.innerHTML += '<div style="width: 100px;height: 2px;border: 1px solid #000;"></div>'; } // 运行之后的当前时间 var d2 = +new Date(); console.log(d2 - d1); } fn(); </script>