javascript 替换节点

本文深入探讨了HTML文档操作中被忽略的方法,包括replaceNode、replaceChild及使用outerHTML进行节点替换。详细解释了每种方法的适用场景、优缺点及使用示例,特别针对IE、Firefox及标准浏览器的差异进行了对比分析。

这可能是最被忽略的文档操作之一,这都怪微软的不作为与W3C的无能,搞到大家只知道appendChild与insertBefore。后来爆出appendChild在IE有bug,好了,以后只用insertBefore了。现在jQuery兴起后,无数赶鸭子上架的javascript素人连基本API也不学了,直接上手append, preppend, before, after与replaceWith,这比较悲哀……好了,我们先来看w3c的替换节点方法吧。

replacedNode = parentNode.replaceChild(newChild, oldChild)。从公式中我们可以看出科学家与工程师亽区别,为了执行它,需要三个节点进行参与,并且返回的是被替换的元素,这不利于链式操作。好处是适用性广,支持XML与HTML。

      var $ = function(id){
        return document.getElementById(id)
      }
       var replace = function(){
        var ul =  $("ul"),
        lis = ul.innerHTML,
        ol = document.createElement("ol");
        ul.parentNode.replaceChild(ol,ul);
        ol.innerHTML = lis;
        replace = function(){}//只允许执行一次
      }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>替换节点 by 司徒正美 </title> <script type="text/javascript"> var $ = function(id){ return document.getElementById(id) } var replace = function(){ var ul = $("ul"), lis = ul.innerHTML, ol = document.createElement("ol"); ul.parentNode.replaceChild(ol,ul); ol.innerHTML = lis; replace = function(){}//只允许执行一次 } </script> </head> <body> <ul id="ul" > <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> </ul> <button type="button" onclick = "replace()" >替换节点</button> </body> </html>

运行代码

oReplace = object.replaceNode(oNewNode)。微软的私有实现,不过只支持HTML。好处是只用到两个节点。

      var $ = function(id){
        return document.getElementById(id)
      }
      var replace = function(){
        var ul =  $("ul"),
        lis = ul.innerHTML,
        ol = document.createElement("ol");
        ul.replaceNode(ol);
        ol.innerHTML = lis;
      }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>替换节点 by 司徒正美 </title> <script type="text/javascript"> var $ = function(id){ return document.getElementById(id) } var replace = function(){ var ul = $("ul"), lis = ul.innerHTML, ol = document.createElement("ol"); ul.replaceNode(ol); ol.innerHTML = lis; } </script> </head> <body> <ul id="ul" > <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> </ul> <button type="button" onclick = "replace()" >替换节点</button> </body> </html>

运行代码

outerHTML方式。非常高效的方式。不用创建节点,不过缺陷也比较多。先说IE,它的XML文档不支持这方法,在HTML中,由于col, colgroup, frameset, html, head, style, title, table, tbody, tfoot, thead, tr, td与th的innerHTML是只读的,因此修改它们时需要用到一些技巧。html,head,title也不说了,基本上操作文档与它不沾边。style元素也用得少,只要是table系列的。修改它们时,找到它们的table一并修改就是。标准浏览器方面,XML不支持,HTML则由于已列入草案,就剩下火狐在负隅顽抗。如果我们要替换的元素有子节点而我们又需要保留它们,这时我们又得考虑这些元素在innerHTML之后的属性恢复问题。参见我的另一篇博文《如何区分属性与特性》,标准浏览器中不用setAttribute设置的属性,会innerHTML中会丢失。因此我们这就要规范人们要用setAttribute设置属性(特性),不要用obj.prop这种纯javascript Object方式。

      var $ = function(id){
        return document.getElementById(id)
      }
      var replace = function(){
        var ul =  $("ul");
        ul.outerHTML = "<ol>"+ul.innerHTML+"</ol>"
        replace = function(){}//只允许执行一次
      }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>替换节点 by 司徒正美 </title> <script type="text/javascript"> var $ = function(id){ return document.getElementById(id) } var replace = function(){ var ul = $("ul"); ul.outerHTML = "<ol>"+ul.innerHTML+"</ol>" replace = function(){}//只允许执行一次 } </script> </head> <body> <ul id="ul" > <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> </ul> <button type="button" onclick = "replace()" >替换节点</button> </body> </html>

运行代码

下面是演示outerHTML在IE表格中遭遇滑铁卢。

      var replace = function(){
        var td =  $("td");
        td.outerHTML = ""+td.innerHTML+""
        replace = function(){}//只允许执行一次
      }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>替换节点 by 司徒正美 </title> <script type="text/javascript"> var $ = function(id){ return document.getElementById(id) } var replace = function(){ var td = $("td"); td.outerHTML = "<th>"+td.innerHTML+"</th>" replace = function(){}//只允许执行一次 } </script> </head> <body> <table border="1"> <tr><td id="td">Ruby Louvre</td></tr> </table> <button type="button" onclick = "replace()" >替换节点</button> </body> </html>

运行代码

修正方法:

      var $ = function(id){
        return document.getElementById(id)
      }
      var getTable = function(el){
        while(el = el.parentNode){
          if(el.tagName.toLowerCase() === "table")
            return el
        }
      }
      var tableObject = {
        "col":1,
        "colgroup":1,
        "tbody":1,
        "tfoot":1,
        "thead":1,
        "tr":1,
        "td":1,
        "th":1
      }//frameset是HTML5要废弃的元素,不管, html, head, title与style出现机率效少,也不管
      var replace = function(){
        var td =  $("td");
        if(!+"\v1" && tableObject[td.tagName.toLowerCase()]){
          var table = getTable(td);
          table.outerHTML = table.outerHTML.replace(td.outerHTML,""+td.innerHTML+"")
        }else{
          td.outerHTML = ""+td.innerHTML+""
        }
        replace = function(){}//只允许执行一次
      }
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>替换节点 by 司徒正美 </title> <script type="text/javascript"> var $ = function(id){ return document.getElementById(id) } var getTable = function(el){ while(el = el.parentNode){ if(el.tagName.toLowerCase() === "table") return el } } var tableObject = { "col":1, "colgroup":1, "tbody":1, "tfoot":1, "thead":1, "tr":1, "td":1, "th":1 }//frameset是HTML5要废弃的元素,不管, html, head, title与style出现机率效少,也不管 var replace = function(){ var td = $("td"); if(!+"\v1" && tableObject[td.tagName.toLowerCase()]){ var table = getTable(td); table.outerHTML = table.outerHTML.replace(td.outerHTML,"<th>"+td.innerHTML+"</th>") }else{ td.outerHTML = "<td>"+td.innerHTML+"</td>" } replace = function(){}//只允许执行一次 } </script> </head> <body> <table border="1"> <tr><th id="td">Ruby Louvre</th></tr> </table> <button type="button" onclick = "replace()" >替换节点</button> </body> </html>

运行代码

总结:以上例子的需求比较变态,都是限定要替换某一节点却不替换它的子节点,如果不考虑其子节点,就方便多。为了效率,我们建议IE用replaceNode,火狐用replaceChild,其他标准浏览器用outerHTML,我们可以把它们封装为一个函数。至于为什么不用innerHTML,好问题,因为要替换的节点可能存在兄弟节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值