读Ext之十二(在各个位置插入元素)
IE 除了发明 innerHTML这个快捷创建DOM元素(及其属性等)外,还发明了insertAdjacentHTML/insertAdjacentText 方法。
它们首次在IE4中引入,随后其它浏览器如Opera、Safari、Chrome相继实现了它们。唯独Firefox没有实现。
(注:2011-11 Firefox8发布,已支持insertAdjacentHTML,但仍未支持insertAdjacentText)
鉴于insertAdjacentHTML被众多浏览器实现,html5已经将 其 列纳入,insertAdjacentText则没那么幸运。
Firefox中使用另外一些方式实现了相同功能。在 这篇 中通过扩展HTMLElement.prototype为Firefox实现了与IE相同的接口方法。
在Ext.DomHelper中,它没有去扩展HTMLElement.prototype(部分人会认为是污染了原生的HTMLElement,暂且放一边)。而是提供了以下四个方法
insertBefore 在元素前面插入新的元素
insertAfter 在元素后面插入新的元素
insertFirst 在元素内部的第一个位置插入新的元素
append 在元素内部最后一个位置插入新的元素
在上一篇中提到了,这四个方法都调用私有的doInsert函数,而doInsert函数内部调用的是Ext.DomHelper的insertHtml方法。
可回到 上一篇 看看那个截图 便一目了然。因此insertHtml方法是实现各种方式插入元素的核心方法,以上是提供给客户端程序员的四个接口方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | insertHtml : function (where, el, html){ var hash = {}, hashVal, setStart, range, frag, rangeEl, rs; where = where.toLowerCase(); // add these here because they are used in both branches of the condition. hash[beforebegin] = [ 'BeforeBegin' , 'previousSibling' ]; hash[afterend] = [ 'AfterEnd' , 'nextSibling' ]; if (el.insertAdjacentHTML) { if (tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){ return rs; } // add these two to the hash. hash[afterbegin] = [ 'AfterBegin' , 'firstChild' ]; hash[beforeend] = [ 'BeforeEnd' , 'lastChild' ]; if ((hashVal = hash[where])) { el.insertAdjacentHTML(hashVal[0], html); return el[hashVal[1]]; } } else { range = el.ownerDocument.createRange(); setStart = 'setStart' + (/end/i.test(where) ? 'After' : 'Before' ); if (hash[where]) { range[setStart](el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling); return el[(where == beforebegin ? 'previous' : 'next' ) + 'Sibling' ]; } else { rangeEl = (where == afterbegin ? 'first' : 'last' ) + 'Child' ; if (el.firstChild) { range[setStart](el[rangeEl]); frag = range.createContextualFragment(html); if (where == afterbegin){ el.insertBefore(frag, el.firstChild); } else { el.appendChild(frag); } } else { el.innerHTML = html; } return el[rangeEl]; } } throw 'Illegal insertion point -> "' + where + '"' ; }, |
insertHtml 的实现也较容易理解,两个分支
分支1,支持el.insertAdjacentHTML的浏览器(IE/Chrome/Safari/Opera)使用el.insertAdjacentHTML
分支2,不支持el.insertAdjacentHTML的浏览器(Firefox)使用range.createContextualFragment+el.insertBefore/el.appendChild
分支1中对table/tr/td元素做了单独处理,相应的私有函数是ieTable,insertIntoTable。insertIntoTable中先创建了一个div再添加table,是因为 IE6/7/8中Table元素的innerHTML Bug 。
Ext.DomHelper 还剩下最后一个方法applyStyles,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | applyStyles : function (el, styles){ if (styles){ var i = 0, len, style; el = Ext.fly(el); if (Ext.isFunction(styles)){ styles = styles.call(); } if (Ext.isString(styles)){ styles = styles.trim().split(/\s*(?::|;)\s*/); for (len = styles.length; i < len;){ el.setStyle(styles[i++], styles[i++]); } } else if (Ext.isObject(styles)){ el.setStyle(styles); } } }, |
设置HTML元素的的样式,设置的方式很灵活,参数styles可以是字符串'color:red',可以是对象{color:red}甚至可以是个函数function(){return 'color:red'}。
el = Ext.fly(el);
该句中的Ext.fly是获取Ext.Element对象,定义在Ext.Element中。后一篇提到了Ext.fly与Ext.get的区别。。
styles = styles.call();
当styles为函数类型时,直接调用该函数,此处用call执行函数,但没有传参数。因此完全可以去掉call直接使用小括号()调用:styles = styles();
函数的各种调用方式见:具名函数的四种调用方式
当styles为字符串类型时,有以下语句
styles = styles.trim().split(/\s*(?::|;)\s*/);
直接使用 trim 方法,但Ext并没有为String扩展该方法,还记得第三篇 原型扩展 ,只给String添加了一个format方法。
1 2 3 4 5 6 7 8 | Ext.applyIf(String, { format : function (format){ var args = Ext.toArray(arguments, 1); return format.replace(/\{(\d+)\}/g, function (m, i){ return args[i]; }); } }); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
2011-05-04 跨域请求之JSONP 二