zhengrenzhe's blog   About

Javascript的cloneNode

今天要实现一个功能,实现思路需要对一个node进行clone,在原node与clone后的node之间随时相互切换,因此需要保证clone后的node与之前的是完全一模一样的。javascript原生提供了clone node的方法:cloneNode

使用cloneNode可以轻易的clone一个node:

var a = document.body.cloneNode()
console.log(a) // <body></body>

cloneNode有一个可选参数,参数为flase或不填时,执行浅度clone,此时只会clone该node本身及它带有的属性,它的子元素,在它上面绑定的event都不会被clone。

当参数为true时,执行深度clone,此时该node的所有子节点都会被clone,通过属性定义的event同样会被clone,但是通过 addEventListeneronxxx = function绑定的event则不会被clone。

<div id="clonenode" data-name="div">
	<p>node1</p>
	<span>node2</span>
</div>
var node = document.getElementById('clonenode');
node.addEventListener('click', function(){
    console.log('click')
});

var a = node.cloneNode(true);
document.body.appendChild(a)

当点击被clone的node时,console显示出了click,但当点击clone返回的元素时,console并没有显示任何信息。从dev tools中可确定clone返回的元素并没有绑定event,通过onxxx绑定的event也是如此。

对于input元素,type为输入类型时,无论深浅clone,输入或选择的值都会被完整的clone。但是对于type为radio时且有name属性时有些例外。因为当radio的name属性值相同时,意味着这些相同name的radio为单选按钮,对radio进行clone时,他们的name也会被clone,若clone前的radio的name都是各不相同的,那么由于name也会被clone,所以8个radio中两两的name时相同的,这就成了单选按钮,clone后因为选中状态也会被clone,而且name相同,所以原先的name就会被抵消,clone返回的node继续被选中。

点击clone后,原先的radio的选中状态会被取消

对于select元素,无论深浅clone,clone返回的node中被选的option并不是clone前的option,也就是选中的状态无法被clone。

假设某个select有三个option,默认为a,当选择c后执行深度clone

可以看到,clone返回的select状态仍为a。

对于textarea元素,无论深浅clone,输入值都不会被clone,但它的尺寸却会被clone。

对于资源加载类元素,link被clone后会重复的发出请求,而script不会。

jQuery的clone

在jQuery(v2.1.4)中也提供了clone node的方法:clone(),该方法接受1~2个参数。当参数为1个时,true表示复制元素与子元素上的event,但是只有当event是通过jquery的方法添加的时,event才会被复制,使用原生的 addEventListeneronxxx = function绑定的event仍不会被clone。false或留空表示不会复制event。当参数为2个时,第1个仍表示是否复制event,第2个表示是否复制子元素。

当需要clone绑定的event时,使用jQuery的最为方便,前提是event是通过jQuery提供的方法绑定的。

← 协同开发时的一些git操作  快速排序非递归实现 →