小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
DOM的操作主要是增删改查,其实还有一个很有意思的操作,就是节点的复制。
复制比新建节点理论是要高效一些的,我们之后也会进行性能测试。
今天我们就进入正题吧,DOM节点的复制。
Node.cloneNode
语法
var dupNode = node.cloneNode(deep);
其有一个参数,表示是不是深度克隆。
true, 则该节点的所有后代节点也都会被克隆,
false, 则只克隆该节点本身。
来看一场经常,复制9个节点,并且里面的值递归增长
<div id="root">
<div class="item">1</div>
</div>
<script type="text/javascript">
const rootEl = document.getElementById("root");
const nodeEl = rootEl.firstChild;
let newNode;
for (let i = 0; i < 10; i++) {
newNode = nodeEl.cloneNode(true);
rootEl.appendChild(newNode);
}
</script>
咋眼一看没问题,其实有两个问题:
- rootEl.firstChild其 实拿到的是Text节点,并不是我们的div节点
div前后都有你看不到的Text节点,所以应该用firstElementChild属性
- 第二个参数为true, 采用了深度复制,结果内容都是1
我们这里只需要浅复制就可以,以节约性能。
换成如下代码:
<div id="root">
<div class="item">1</div>
</div>
<script type="text/javascript">
const rootEl = document.getElementById("root");
const nodeEl = rootEl.firstChild;
let newNode;
for (let i = 0; i < 10; i++) {
newNode = nodeEl.cloneNode(false);
newNode.innerText = i + 1;
rootEl.appendChild(newNode);
}
</script>
完美!!!
完美了吗? 没有啊,兄弟!, 事件呢?
事件的复制
我们先看看一个简单的例子:
我们复制一个button,这个button通过addEventListener注册了一个事件,我们对这个button进行深复制。
<div id="root">
<button class="item">点我啊</button>
</div>
<script>
const rootEl = document.getElementById("root");
const nodeEl = rootEl.firstElementChild;
function onClick(){
alert("clicked")
}
nodeEl.addEventListener("click", onClick);
const newEl = rootEl.cloneNode(true);
rootEl.appendChild(newEl);
</script>
确实得到了两个按钮,但是被复制的按钮被点击后,并没有弹出alert框。
说明,通过addEventListener添加的事件并不能被复制。
我们稍作改动:
<div id="root">
<button class="item" onclick="alert('clicked')">点我啊</button>
</div>
<script>
const rootEl = document.getElementById("root");
const nodeEl = rootEl.firstElementChild;
const newEl = rootEl.cloneNode(true);
rootEl.appendChild(newEl);
</script>
被复制的按钮点击事件生效了,哈哈,不错不错。
我们再稍作改动:
<div id="root">
<button class="item">点我啊</button>
</div>
<script>
function onClick() {
alert("clicked");
}
const rootEl = document.getElementById("root");
const nodeEl = rootEl.firstElementChild;
nodeEl.onclick = onClick;
const newEl = rootEl.cloneNode(true);
rootEl.appendChild(newEl);
</script>
经过测试也没有弹出alert框
结论:
- DOM2
addEventListener注册的事件不会被复制 - DOM0 节点上
onclick属性的事件会被复制,但是通过JS动态添加的onclick不会被复制。
小结
当然复制节点的方法不止有cloneNode方法,下期再见。
今天你收获了吗?