节点插入
对于早期的w3c浏览器,并没有实现ie的私有方法insertAdjacentHTML(目前已是HTML5标准),可以用appendChild模拟该方法的实现:
if(typeof HTMLElement !=='undefined' && !HTMLElement.prototype.insertAdjacentHTML){ var insertAdjacentElement = function(node,position,el){ switch (position.toLowerCase()){ case 'beforebegin': node.parentNode.insertBefore(el,node); break; case 'afterbegin': node.insertBefore(el,node.firstChild); break; case 'beforeend': node.appendChild(el); break; case 'afterend': if(node.nextSibling){ node.parentNode.insertBefore(el,node.nextSibling); }else{ node.parentNode.appendChild(el); } break; } }; HTMLElement.prototype.insertAdjacentHTML = function(position,html){ var range = document.createRange(),frag, parent; range.setStart(document.body); frag = range.createContextualFragment(html); if(this.nodeType == 3 || this.nodeType == 8){ parent = this.parentNode; insertAdjacentElement(parent,position,frag); }else{ insertAdjacentElement(this,position,frag); } } }
使用了Range.createContextualFragment(html)方法,MDN对该方法叙述:The Range.createContextualFragment()
method returns a DocumentFragment
by invoking the HTML fragment parsing algorithm or the XML fragment parsing algorithm with the start of the range (the parent of the
selected node) as the context node. The HTML fragment parsing algorithm is used if the range belongs to a Document
whose HTMLness bit
is set. In the HTML case, if the context node would be html
, for historical reasons the fragment parsing algorithm is invoked with body
as the context instead. 也就是说,选中节点的父节点(即Range对象的startContainer属性)为HTML(XML)文档片段解析算法的上下文节点。
该方法兼容Chrome,Firefox,IE11,以及Opera15.对于模拟insertAdjacentHTML足够用。当然也可使用兼容性没有问题的DocumentFragment对象。
但是出于好奇,我用了jsperf对插入节点的各个方法进行性能分析,发现依旧是appendChild的插入方法效率最高(指的是单位时间内的操作数)。
另外,对于innerHTML插入的易用性是不言而喻的,通常我们用一系列拼接的字符串给innerHTML赋值,此时会调用js解析器,将解析的相关节点
作为该元素的子节点。这个属性兼容性没有问题。相应的也有outerHTML属性,这个兼容性也没有多大问题,除非你是用的是Firefox 11之前的版本。
对于outerHTML可以用innerHTML做一些兼容性。
1 //对Firefox 11- 版本做兼容,其不支持outerHTML属性 2 function getOuterHtml(){ 3 var e = document.createElement("div"); 4 e.appendChild(this); 5 return e.innerHTML; 6 } 7 function setOuterHtml(){ 8 var e = document.createElement("div"); 9 var p = this.parentNode; 10 e.appendChild(this); 11 while(e.firstChild){ 12 p.insertBefore(e.firstChild,this); 13 } 14 p.removeChild(this); 15 } 16 17 if(Object.defineProperty){ 18 Object.defineProperty(Element.prototype,"outerHTML",{ 19 get: getOuterHtml, 20 set: setOuterHtml, 21 enumerable: false, 22 configurable: false 23 }) 24 }else{ 25 Element.prototype.__defineGetter__("outerHTML",getOuterHtml); 26 Element.prototype.__defineSetter__("outerHTML",setOuterHtml); 27 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了