2

オブジェクトをパラメーターとして受け取り、オブジェクトの構造を使用してネストされたDOMノードを作成する関数がありますが、次のエラーが発生します。

http://new.app/:75NOT_FOUND_ERR: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.

関数に実行させたいのは、適切なオブジェクトをパラメーターとして指定した場合の例です。

var nodes = {
    tweet: {
        children: {
            screen_name: {
                tag: "h2"
            },
            text: {
                tag: "p"
            }
        },
        tag: "article"
    }
};

次のDOMノードが作成されます。

<article>
    <h2></h2>
    <p></p>
</article>

これまでの私の試みは次のとおりです。

function create(obj) {
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        if(obj[i].children) {  
            tmp.appendChild(create(obj[i].children)); /* error */
        }; 
        document.getElementById("tweets").appendChild(tmp);  
    };  
};

私はすでに苦労しています!

tag理想的には、最終的には、各オブジェクトだけでなく、id, innerHTML, classなどにも子キーを追加したいと思います。

フレームワークやライブラリは、ほんの数行のコードなどでこれを実行できると確信していますが、この特定のプロジェクトでは使用したくないと思います。

あなたの答えも簡単に説明できれば、これがどのように機能するのか、そしてどこが間違っているのかを学ぶのに本当に役立ちます!

ありがとうございました!

注意:エラーメッセージが話している関数の行を変更してマークを付けました。

私はそれを以下から変更しました:

mp.appendChild(obj[i].children);

に:

mp.appendChild(create(obj[i].children));

これは、子オブジェクト内のネストされたキーも作成する必要screen_nameがあるためです。子キーがあれば、それらも作成されます。申し訳ありませんが、これを理解していただければ幸いです。

私はいくつかのポインタについてhttp://jsperf.com/create-nested-dom-structureを見ています、これもあなたを助けるかもしれません!

4

3 に答える 3

2

「作成」関数は再帰的に作成する必要があります。

データからノードを作成するには(一般的に)、次のことを行う必要があります。

  1. 「tag」プロパティを見つけて、新しい要素を作成します
  2. 要素に要素の「id」値を指定します(データから取得)
  3. 「子」の要素ごとに、ノードを作成して追加します

したがって:

function create(elementDescription) {
  var nodes = [];
  for (var n in elementDescription) {
    if (!elementDescription.hasOwnProperty(n)) continue;
    var elem = elementDescription[n];
    var node = document.createElement(elem.tag);
    node.id = n; // optional step
    var cnodes = create(elem.children);
    for (var c = 0; c < cnodes.length; ++c)
      node.appendChild(cnodes[c]);
    nodes.push(node);
  }
  return nodes;
}

これにより、元の「仕様」オブジェクトから作成されたドキュメント要素の配列が返されます。したがって、あなたの例から、あなたは次のように呼ぶでしょう:

var createdNodes = create(nodes);

「createdNodes」は、1つの要素の配列、<article>IDが「tweets」のタグになります。その要素には<h2>、IDが「screen_name」の<p>タグとIDが「text」のタグの2つの子があります。(今考えてみると、ノードの説明に明示的な「id」エントリなどがない限り、「id」の割り当てをスキップすることをお勧めします。)

したがって<div>、ページに「tweets」という名前がある場合(例を使用する場合は、関数の「id」設定部分を確実に切り取りたいと思います)、次のような結果を追加します。

var createdNodes = create(nodes), tweets = document.getElementById('tweets');

for (var eindex = 0; eindex < createdNodes.length; ++eindex)
  tweets.appendChild(createdNodes[eindex]);
于 2010-11-17T15:44:46.743 に答える
0

要素のリストを受け入れる関数appendListと、追加するコンテナーを追加しました。コードをより効果的に分離するために、create関数から「ツイート」部分への追加を削除しました。

function create(obj) {
    var els = [];
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        var children;
        if(children = obj[i].children) {  
            var childEls = create(children);
            appendList(childEls, tmp);
        }
        els.push(tmp);
    }; 
    return els;
};
function appendList(list, container){
    for(var i = 0, el; el = list[i]; i++){
        container.appendChild(el);
    }
};
// gets an array of root elements populated with children
var els = create(nodes); 
// appends the array to "tweets"
appendList(els, document.getElementById("tweets")); 
于 2010-11-17T15:30:39.867 に答える
-1

前の答えに基づいて:追加しようとしている要素を作成する必要があると思います:

tmp.appendChild(children [prop] .tag);

する必要があります

tmp.appendChild(document.createElement(children [prop] .tag));

function create(obj) {
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        var children;
        if(children = obj[i].children) {  
            for(var prop in children)
                tmp.appendChild(document.createElement(children[prop].tag));   
        }
        document.getElementById("tweets").appendChild(tmp);  
    };  
};
于 2010-11-17T15:45:05.093 に答える