私のダイナミックjavascriptオブジェクトはDOM元素のジェネレータになります.

5994 ワード


 
06年にobjectをDOM元素に変換するジェネレータを書いたことがありますが、転職してからしばらくjsを書かないとコードが見つかりません.しかし、最近は仕事が必要なので、もう一つ書き直しました.でも今は多くのjsコードバンクがこの技術を実現したようです.もう新鮮ではありません.
 
コードの原理は簡単です.つまり、簡単なjsオブジェクトです.その中のnodeNameフィールド値からdocument.create Element()を呼び出してDOM要素を生成し、jsオブジェクトの残りのフィールド値を新たに生成したDOM要素に設定します.まずデモコードを見て、表を生成するために、各セルに一つのcheckboxを保存します.
 
 
    var table = {nodeName: "table", className: "selection", children:[]};
    var ctrls;
    for(var i = 0; i < infos.length; ++i)
    {
        if( i % 5 == 0 )
        {
            var row = {nodeName: "tr", children:[]};
            ctrls = row.children;
            table.children.push(row);
        }
        ctrls.push({nodeName: "td", className: "select_project", children:[
            {nodeName:"input", "id": "proj_" + infos[i].id, name:"selproj", "type": "radio", value:infos[i].id, onclick: fnOnProjectCheck}
            , {nodeName: "label", "htmlFor": "proj_" + infos[i].id, innerHTML: infos[i].lname}
        ]});
    }

    containor.innerHTML = "";
    generateElements(containor, table);
 
 直接の文字列でつづり合わせると、そんなにすっきりしないように見えます.使っているうちに一番便利なのは何百行もの表を作ったことです.表が長いので、20行ごとに1行の表を差し込む必要があります.この技術を使うと実に多くの重複作業が簡略化されます.
 
  簡単に使用するには、GEnerate Elementsを呼び出して、二つのパラメータが入ってきます.一つは容器DOMオブジェクトで、一つは作成するノード記述情報です.記述情報オブジェクトは純粋なjsオブジェクトであり、ここでは、
 
  • は、作成するDOMオブジェクトのnodeName値、例えば「table」、「div」などの
  • を含む必要があります.
  • 他の属性は、DOMオブジェクトの属性に直接付与される
  • である.
  • children属性が含まれている場合、この属性に対応する値はサブ要素として
  • を作成する.
    generate Elementsのパラメータと使用の組み合わせは以下の通りです.
  • parent DomElement:任意で、生成ノードのコンテナオブジェクトを格納する.
  • パラメータが存在すると、生成された要素が自動的にコンテナオブジェクトに追加され、作成された要素が同時にスケジューラ
  • に戻る.
  • 省略されている場合は、DOM要素を作成することだけを助けて、その後、调节者
  • に戻る.
  • options:コンテンツに応じてDOM要素を作成します.
  • タイプは配列であり、各配列要素は一つのoptionオブジェクトであり、最終的にDOM要素のセット
  • を生成する.
  • タイプは対象となります.optionオブジェクトの定義を参照して、DOM要素
  • を生成します.
     
    オブジェクトフィールドの定義:
     
  • nodeNameまたはtagName:必ず、DOMオブジェクトに対応するタグ値
  • children:サブ要素定義
  • タイプは配列であり、各配列要素は一つのオプトモーションオブジェクトであり、複数のサブ要素を含む
  • を表す.
  • タイプは対象としています.1つのサブ要素を含む
  • を表します.
  • 他の属性:直接DOMオブジェクトにコピーし、再帰的な入れ子コピーはサポートされていません.例えば、style.background Colorのような形では、DOMに対応するstyle属性のbackground Colorにコピーできません.
    他の話は多く話しません.コードを入れます.
     
    // return element that generated
    function generateElements(parentElem, info)
    {
        if( parentElem == null ) return null;
        if( info == null )
        {
            if( parentElem.ownerDocument == document ) return null;
            info = parentElem;  // means single argument
            parentElem = null;
        }
    
        if( info instanceof Array )
        {
            var elems = [];
            for(var i = 0; i < info.length; ++i)
                elems.push(generateElements(parentElem, info[i]));
            return elems;
        }
        else
        {
            var pName = parentElem? parentElem.nodeName.toLowerCase(): "";
            var nodeName = (info.nodeName||info.tagName).toLowerCase();
    
            var fnCreate = function(p, n){return document.createElement(n);};
            var fnAppend = function(p, el){p.appendChild(el);};
    
            if( "table" == pName )
            {
                fnAppend = empty;
                if( "thead" == nodeName )
                    fnCreate = function(p, n){ return p.createTHead(); };
                else if( "tfoot" == nodeName )
                    fnCreate = function(p, n){ return p.createTFoot(); };
                else if( "tr" == nodeName )
                    fnCreate = function(p, n){
                        return p.insertRow(-1);
                    };
                else
                    fnCreate = empty;
            }
            else if( indexOfArray(["tbody", "thead", "tfoot"], pName) != -1 )
            {
                fnAppend = empty;
                if( "tr" == nodeName )
                    fnCreate = function(p, n){
                        return p.insertRow(-1);
                    };
                else
                    fnCreate = empty;
            }
            else if( "tr" == pName )
            {
                if( "td" == nodeName )
                {
                    fnCreate = function(p, n){ return p.insertCell(-1); };
                    fnAppend = empty;
                }
            }
    
            var elem = fnCreate(parentElem, nodeName);
            if( elem )
            {
                // fill properties
                var filtered_props = ["children", "nodeName", "tagName", "children"];
    
                for(var prop in info)
                {
                    if( prop.length > 0 && prop.charAt(0) != '_' && indexOfArray(filtered_props, prop) == -1)
                        elem[prop] = info[prop];
                }
                // create children
                if( info.children )
                    generateElements(elem, info.children);
                // append child
                if( parentElem )
                    fnAppend(parentElem, elem);
            }
    
            return elem;
        }
    
    }
     
    上記のコードには以下のような改善が必要なところがあります.
     
  • 属性の設定は標準のsetAttributeを使用していませんが、現在はie、ff、chromeの中で
  • を使用しています.
  • 直接returnによって作成されたDOMオブジェクトは、メモリ漏れの原因となりますか?私はテストに行きませんでした.
  • は、プロパティのネスト設定をサポートしています.すなわち、スタイル.xxxをそのままDOMのスタイル属性に設定できるはずです.
  • 使用中、使用者は慎重に使用しなければなりません.jQueryにはこの機能が含まれていないようです.何の原因か分かりません.メモリ漏れを誘発できるかもしれません.