深入理解javascript动态插入技术(6)

insert方法在实现火狐插入操作中,使用了W3C DOM Range对象的一些罕见方法,具体可到火狐官网查看。下面实现把字符串转换为节点,利用innerHTML这个伟大的方法。Prototype.js称之为_getContentFromAnonymousElement,但有许多问题,dojo称之为_toDom,mootools的Element.Properties.html,jQuery的clean。Ext没有这东西,它只支持传入HTML片断的insertAdjacentHTML方法,不支持传入元素节点的insertAdjacentElement。但有时,我们需要插入文本节点(并不包裹于元素节点之中),这时我们就需要用文档碎片做容器了,insert方法出场了。

复制代码 代码如下:


parseHTML : function(htmlStr, fragment){
    var div = dom.doc.createElement("div"),
    reSingleTag =  /^<(\w+)\s*\/?>$/;//匹配单个标签,如<li>
    htmlStr += '';
    if(reSingleTag.test(htmlStr)){//如果str为单个标签
        return  [dom.doc.createElement(RegExp.$1)]
    }
    var tagWrap = {
        option: ["select"],
        optgroup: ["select"],
        tbody: ["table"],
        thead: ["table"],
        tfoot: ["table"],
        tr: ["table", "tbody"],
        td: ["table", "tbody", "tr"],
        th: ["table", "thead", "tr"],
        legend: ["fieldset"],
        caption: ["table"],
        colgroup: ["table"],
        col: ["table", "colgroup"],
        li: ["ul"],
        link:["div"]
    };
    for(var param in tagWrap){
        var tw = tagWrap[param];
        switch (param) {
            case "option":tw.pre  = '<select multiple="multiple">'; break;
            case "link": tw.pre  = 'fixbug<div>';  break;
            default : tw.pre  =   "<" + tw.join("><") + ">";
        }
        tw.post = "</" + tw.reverse().join("></") + ">";
    }
    var reMultiTag = /<\s*([\w\:]+)/,//匹配一对标签或多个标签,如<li></li>,li
    match = htmlStr.match(reMultiTag),
    tag = match ? match[1].toLowerCase() : "";//解析为<li,li
    if(match && tagWrap[tag]){
        var wrap = tagWrap[tag];
        div.innerHTML = wrap.pre + htmlStr + wrap.post;
        n = wrap.length;
        while(--n >= 0)//返回我们已经添加的内容
            div = div.lastChild;
    }else{
        div.innerHTML = htmlStr;
    }
    //处理IE自动插入tbody,如我们使用dom.parseHTML('<thead></thead>')转换HTML片断,它应该返回
    //'<thead></thead>',而IE会返回'<thead></thead><tbody></tbody>'
    //亦即,在标准浏览器中return div.children.length会返回1,IE会返回2
    if(dom.feature.autoInsertTbody && !!tagWrap[tag]){
        var ownInsert = tagWrap[tag].join('').indexOf("tbody") !== -1,//我们插入的
        tbody = div.getElementsByTagName("tbody"),
        autoInsert = tbody.length > 0;//IE插入的
        if(!ownInsert && autoInsert){
            for(var i=0,n=tbody.length;i<n;i++){
                if(!tbody[i].childNodes.length )//如果是自动插入的里面肯定没有内容
                    tbody[i].parentNode.removeChild( tbody[i] );
            }
        }
    }
    if (dom.feature.autoRemoveBlank && /^\s/.test(htmlStr) )
        div.insertBefore( dom.doc.createTextNode(htmlStr.match(/^\s*/)[0] ), div.firstChild );
    if (fragment) {
        var firstChild;
        while((firstChild = div.firstChild)){ // 将div上的节点转移到文档碎片上!
            fragment.appendChild(firstChild);
        }
        return fragment;
    }
    return div.children;
}

嘛,基本上就是这样,运行起来比jQuery快许多,代码实现也算优美,至少没有像jQuery那样乱成一团。jQuery还有四个反转方法。下面是jQuery的实现:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdzyyg.html