节点操作
克隆节点
- node.cloneNode(deep)
- deep: 默认为false
- deep 为 true, 克隆元素及属性,以及元素的内容和后代
- deep 为 false, 只克隆元素本身,及它的属性
<!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>
#box1 {
width: 100px;
height: 100px;
background: red;
border: 2px solid #000;
}
</style>
</head>
<body>
<div id="box">
<div id="box1">
<div>这是一个div</div>
</div>
</div>
<script>
{
let box = document.querySelector("#box");
let box1 = document.querySelector("#box1");
console.log(box1.cloneNode());
}
</script>
</body>
</html>
node.cloneNode(deep) 返回调用该方法的节点的一个副本.。
这里打印的内容中并没有拷贝“标签内容”,因此小编这里的版本默认值是false,即进行了浅拷贝(只克隆元素本身,及它的属性。)。
注意:
在 DOM4 规范中(实现于Gecko 13.0(Firefox 13.0 / Thunderbird 13.0 / SeaMonkey 2.10)),deep是一个可选参数。如果省略的话,参数的默认值为 true,也就是说默认是深度克隆。但在最新的规范里,该方法的行为已经改变了,其默认值变成了 false。
虽然该参数仍旧是可选的,但是溜_x_i_a_o_迪童鞋建议你必须要为该方法设置 deep 参数,无论是为了向前还是向后兼容考虑。
let box = document.querySelector("#box");
let box1 = document.querySelector("#box1");
box1.onclick =()=>{
alert(1);
}
box.appendChild(box1.cloneNode());
点击没有反应,因此溜_x_i_a_o_迪童鞋在这里认为浅克隆(克隆),是不能克隆事件的。
尝试深克隆,发现内容进行了拷贝,但是事件不可进行拷贝。因此可得出结论,克隆始终不能克隆事件。
let box = document.querySelector("#box");
let box1 = document.querySelector("#box1");
box1.onclick =()=>{
alert(1);
}
box.appendChild(box1.cloneNode(true));
文档碎片
很多小小白可能会这样写代码,溜_x_i_a_o_迪童鞋并不建议你这样做,因为每加载一次循环都会导致页面重新渲染一次,这样会导致大大削减网页的性能。
<!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>
#box div{
float: left;
width: 100px;
height: 100px;
background: red;
margin: 10px;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
{
let box = document.querySelector("#box");
for (let i = 0;i < 1000;i++){
box.innerHTML += `<div>${i}</div>`;
}
}
</script>
</body>
</html>
跟溜_x_i_a_o_迪童鞋一样嫩的小白可能会这样优化代码:
let box = document.querySelector("#box");
let inner = "";
for (let i = 0;i < 1000;i++){
inner += `<div>${i}</div>`;
}
box.innerHTML = inner;
光看代码可能无法直观看出性能差异,我们可以做一下简单的性能检测
{
let box = document.querySelector("#box");
let inner = "";
console.time(1);
for (let i = 0;i < 1000;i++){
box.innerHTML += `<div>${i}</div>`;
}
console.timeEnd(1);
}
可以很直观看出两者性能的差异,希望咱们在开发过程中,还是多多思考有关性能优化的事情,这样几秒几秒的累加,会使程序性能越发强大。
let box = document.querySelector("#box");
let inner = "";
console.time(1);
for (let i = 0;i < 1000;i++){
inner += `<div>${i}</div>`;
}
box.innerHTML = inner;
console.timeEnd(1);
用DOM的node.appendChild、document.createElement方法:
let box = document.querySelector("#box");
console.time(1);
for (let i = 0;i < 1000;i++){
let div = document.createElement("div");
div.innerHTML = i;
box.appendChild(div);
}
console.timeEnd(1);
我们发现与之前我们所做优化的性能是雷同的!
文档碎片(性能优化)
DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档碎片,将元素附加到文档碎片,然后将文档碎片附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能。
let box = document.querySelector("#box");
console.time(1);
let fragment = document.createDocumentFragment(); // 文档碎片
for(let i = 0; i < 1000; i++){
let div = document.createElement("div");
div.innerHTML = i;
fragment.appendChild(div); // 先把div放入文档碎片里
}
box.appendChild(fragment); // 最后把文档碎片放入DOM中
console.timeEnd(1);
我们可以法此时速度更快了,性能最优!
注意:
可能不能的配置的电脑,运行速度都会有差异,并且每次运行时间都有可能不一样,所以各位和小编一样小白的伙计们,不用太在意!
(后续待补充)