javascript 替换节点
这可能是最被忽略的文档操作之一,这都怪微软的不作为与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 (){} //只允许执行一次 } |
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; } |
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 (){} //只允许执行一次 } |
下面是演示outerHTML在IE表格中遭遇滑铁卢。
var replace = function (){ var td = $( "td" ); td.outerHTML = "" +td.innerHTML+ "" replace = function (){} //只允许执行一次 } |
修正方法:
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 (){} //只允许执行一次 } |
总结:以上例子的需求比较变态,都是限定要替换某一节点却不替换它的子节点,如果不考虑其子节点,就方便多。为了效率,我们建议IE用replaceNode,火狐用replaceChild,其他标准浏览器用outerHTML,我们可以把它们封装为一个函数。至于为什么不用innerHTML,好问题,因为要替换的节点可能存在兄弟节点。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义