读Ext之十二(在各个位置插入元素)

本文介绍了不同浏览器下使用insertAdjacentHTML及Ext.DomHelper提供的替代方法来插入DOM元素的技术细节,并探讨了适用于Firefox的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IE 除了发明 innerHTML这个快捷创建DOM元素(及其属性等)外,还发明了insertAdjacentHTML /insertAdjacentText 方法。

它们首次在IE4中引入,随后其它浏览器如Opera、Safari、Chrome相继实现了它们。唯独Firefox没有实现。

鉴于insertAdjacentHTML被众多浏览器实现,html5已经将 列纳入,insertAdjacentText则没那么幸运。

Firefox中使用另外一些方式实现了相同功能。在 这篇   中通过扩展HTMLElement.prototype为Firefox实现了与IE相同的接口方法。

在Ext.DomHelper中,它没有去扩展HTMLElement.prototype(部分人会认为是污染了原生的HTMLElement,暂且放一边)。而是提供了以下四个方法

 

insertBefore  在元素前面插入新的元素
insertAfter   在元素后面插入新的元素
insertFirst   在元素内部的第一个位置插入新的元素
append        在元素内部最后一个位置插入新的元素

 

在上一篇中提到了,这四个方法都调用私有的doInsert函数,而doInsert函数内部调用的是Ext.DomHelper的insertHtml方法。
可回到 上一篇 看看那个截图 便一目了然。因此insertHtml方法是实现各种方式插入元素的核心方法,以上是提供给客户端程序员的四个接口方法。

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,

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方法。

Ext.applyIf(String, {
    format : function(format){
        var args = Ext.toArray(arguments, 1);
        return format.replace(/\{(\d+)\}/g, function(m, i){
            return args[i];
        });
    }
});

 

这是一个bug ,另见 trim的各种实现

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值