善用 cloneNode 存储 DOM 对象
获取DOM节点的方法有很多,如常用的getElementById()、getElementsByTagName(),前者返回一个节点元素,后者返回的是节点的集合。看似相同,实际上其中大有文章:
1、getElementById()
返回的节点可以保存到变量中,即便使用removeChild()方法移除,也能再通过保存的变量使用该节点。
测试下面的代码:
<div id="test">hello world</div>
<script type="text/javascript">
(function(){
var oDiv = document.getElementById('test');
document.body.removeChild(oDiv);
alert(oDiv.innerHTML);//hello world
})()
</script>
2、getElementsByTagName()
返回的值仅仅是对DOM节点地址的引用,如果使用removeChild()删除节点,返回值是会变化的。可能用图示更清晰吧
测试下面的代码加深印象:
<ul id="test"> <li>hello world</li> <li>hello world2</li></ul><script type="text/javascript">
(function(){
var oDiv = document.getElementById('test'),oLi = document.getElementsByTagName('LI');
oDiv.removeChild(oLi[0]);
alert(oLi[0].innerHTML);//期望的是hello world,实际上输出的是hello world2
})()
</script>
这种引用问题时有发生,解决的方法可用数组结合去存储返回值,类似于getElementById:
<ul id="test"> <li>hello world</li> <li>hello world2</li></ul><script type="text/javascript">
(function(){
var oDiv = document.getElementById('test'),oLi = document.getElementsByTagName('LI'),arr = [];
arr[0] = oLi[0];
arr[1] = oLi[1];//数量多了可用循环遍历
oDiv.removeChild(oLi[0]);
alert(arr[0].innerHTML);//hello world
})()
</script>
不过问题又来了,如果我们用innerHTML=”"代替removeChild,你会发现在IE浏览器下最后的输出会是空的。
<ul id="test"> <li>hello world</li> <li>hello world2</li></ul><script type="text/javascript">
(function(){
var oDiv = document.getElementById('test'),oLi = document.getElementsByTagName('LI'),arr = [];
arr[0] = oLi[0];
arr[1] = oLi[1];//数量多了可用循环遍历
oDiv.innerHTML='';
alert(arr[0].innerHTML);//IE下为空
})()
</script>
再次改进存储方法,使用强大的cloneNode()
<ul id="test"> <li>hello world</li> <li>hello world2</li></ul><script type="text/javascript">
(function(){
var oDiv = document.getElementById('test'),oLi = document.getElementsByTagName('LI'),arr = [];
arr[0] = oLi[0].cloneNode(true);
arr[1] = oLi[1].cloneNode(true);
oDiv.innerHTML='';
alert(arr[0].innerHTML);//hello world
})()
</script>