• 读Ext之十一(通过innerHTML创建元素)


    innerHTML 这个由 IE 引入的属性成了事实标准,各浏览器均支持。尽管html4中没有承认它,但html5已经正式将其纳入 。

    我们知道任何一个库都少不了DOM操作,因为用JS操作DOM(早期微软称DHTML)是日常开发中最基本的工作之一。

    这篇主要讲述Ext.DomHelper中的 createHtml 函数。首先Ext.DomHelper为一个单例对象。使用其时可沿用Ext库的习惯使用别名dh

    var dh = Ext.DomHelper; // 使用dh别名
    

     

    dh有以下方法:
    markup
    applyStyles
    insertHtml
    insertBefore
    insertAfter
    insertFirst
    append
    overwrite
    createHtml
     

    dh的createHtml方法就是整个闭包中私有的createHtml。
    dh的markup方法内部调用的就是整个闭包中私有的createHtml。
    dh的overwrite方法内部也用到了createHtml。

    此外私有的doInsert函数内部用用到了createHtml,而dh的insertBefore、insertAfter、insertFirst、append方法用到了doInsert。
    因此可以看到私有的createHtml函数是dh中处在底层的,最重要的函数 。它们之间的关系如下图

    createHtml 的定义如下

    function createHtml(o){
        var b = '',
            attr,
            val,
            key,
            keyVal,
            cn;
    
        if(Ext.isString(o)){
            b = o;
        } else if (Ext.isArray(o)) {
            for (var i=0; i < o.length; i++) {
                if(o[i]) {
                    b += createHtml(o[i]);
                }
            };
        } else {
            b += '<' + (o.tag = o.tag || 'div');
            Ext.iterate(o, function(attr, val){
                if(!/tag|children|cn|html$/i.test(attr)){
                    if (Ext.isObject(val)) {
                        b += ' ' + attr + '="';
                        Ext.iterate(val, function(key, keyVal){
                            b += key + ':' + keyVal + ';';
                        });
                        b += '"';
                    }else{
                        b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
                    }
                }
            });
            // Now either just close the tag or try to add children and close the tag.
            if (emptyTags.test(o.tag)) {
                b += '/>';
            } else {
                b += '>';
                if ((cn = o.children || o.cn)) {
                    b += createHtml(cn);
                } else if(o.html){
                    b += o.html;
                }
                b += '</' + o.tag + '>';
            }
        }
        return b;
    }
    

    虽然代码较多,但接口却很简单:传入了一个参数o,返回了一个字符串b。

    createHtml 内部有三个分支

    分支1 ,参数o为字符串时直接返回
    分支2 ,参数o为数组时递归调用自身.Ext.isArray用来判断所传参数是否为一个数组类型,该方法在 读Ext之二(实用方法) 中提到。
    分支3 ,参数o为对象时(通常使用最多的情况)

    分之一的情况很简单

    var str = createHtml('<div>test</div>');
    alert(str); // "<div>test</div>"
    

    分支二的情况

    var str = createHtml(['<div>test</div>','<p>pp</p>']);
    alert(str); // "<div>test</div><p>pp</p>"
    

    分支三的情况

    var obj = {
            tag:'ul',
            children:[{tag:'li',html:'li 1'},{tag:'li',html:'li 2'}]
        };
    var str = createHtml(obj);
    alert(str); // "<ul><li>li 1</li><li>li 2</li></ul>"
    

    分支三的详细情况如下

    b += '<' + (o.tag = o.tag || 'div');
    

    b为空字符串,该语句执行完为:"<tag",如果没有所传对象没有tag属性,默认创建div即"<div"

    接下来是为根元素添加属性,

    Ext.iterate(o, function(attr, val){
        if(!/tag|children|cn|html$/i.test(attr)){
            if (Ext.isObject(val)) {
                b += ' ' + attr + '="';
                Ext.iterate(val, function(key, keyVal){
                    b += key + ':' + keyVal + ';';
                });
                b += '"';
            }else{
                b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
            }
        }
    });
    

    Ext.iterate方法是一个通用迭代器,可以迭代数组,也可以是对象。在 读Ext之二 提到。即所传对象o的属性不为tag、children、cn、html时给该元素添加html属性

    var obj = {
        tag: 'input',
        name: 'uname',
        cls: 'myClass',
        id: 'myId'
    };
    var str = createHtml(obj); // 创建input元素,添加name、class及id属性
    alert(str); // <input name="uname" class="myClass" id="myId"/>
    

    对html元素的class,for属性做了特殊处理,因为js中class是保留字,for是关键字。

    此外有些属性值是复合值组成,如style

    var obj = {
        tag: 'p',
        style: {'100px',height:'100px',background:'red'}
    };
    var str = createHtml(obj);
    alert(str); // <p style="100px;height:100px;background:red;"></p>
    

    接下来

    if (emptyTags.test(o.tag)) {
        b += '/>';
    }

    emptyTags 是一个正则,这句是对非闭合标签的处理,非闭合标签如br、input、img等。
    所有的非闭合标签,都会以"/>"结束,这里遵循xml的习惯。对于非闭合标签不会有html内容。

    接下来

    else {
        b += '>';
        if ((cn = o.children || o.cn)) {
            b += createHtml(cn);
        } else if(o.html){
            b += o.html;
        }
        b += '</' + o.tag + '>';
    }

    对于闭合标签,先完成首标签闭合。拿div示例,由先"<div"变成了"<div>"。

    接下来如果有children或cn属性,则添加子元素,是一个递归调用,即子元素如果有属性,子元素仍然会继续递归添加。
    最后是结束标签"</div>"

    这就是这个createHtml函数了。该函数实现的很紧凑,巧妙。

    createHtml最终返回的是html片段,该片段会通过innerHTML添加到文档中去。
    上面的关系图已经可以看到:

    markup方法直接调用了createHTML

    markup : function(o){
        return createHtml(o);
    },
    

    个人认为这个方法和markup方法重复了。


    doInsert方法也直接调用了createHtml

    function doInsert(el, o, returnElement, pos, sibling, append){
        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
        return returnElement ? Ext.get(newNode, true) : newNode;
    }

     

    好了,下一篇会接着看DomHelper的其它方法。

     

     

    DomHelper.js 

  • 相关阅读:
    Sharepoint2013搜索学习笔记之创建搜索服务(二)
    Sharepoint2013搜索学习笔记之设置外网内容源(四)
    C# zxing插件 根据输入的字符串生成二维码
    值类型和引用类型
    Web.config增删查改
    Redis
    2017年最好的6个WEB前端开发手册下载
    php implode()函数详解
    elk日志系统搭建
    aop实现接口请求参数打印
  • 原文地址:https://www.cnblogs.com/snandy/p/2478021.html
Copyright © 2020-2023  润新知