Domanda

Ho una funzione che prende un oggetto come parametro, e utilizza la struttura dell'oggetto per creare nodi DOM nidificati, ma ricevo il seguente errore:

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.

Quello che vorrei la mia funzione di fare, è, a fonti di un oggetto adatto come parametro, ad esempio:

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

Si creerebbe i nodi seguenti DOM:

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

Ecco il mio tentativo finora:

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);  
    };  
};

Sono già alle prese!

Idealmente mi piacerebbe aggiungere alla fine più chiave figlio di a ciascun oggetto, non solo tag, ma anche id, innerHTML, class etc.

Qualsiasi hel sarebbe molto apprezzato, anche se per favore: sono sicuro che un quadro o biblioteca può fare questo per me in poche righe di codice, o qualcosa di simile, ma 'd preferiscono non utilizzare uno per questo particolare progetto.

Se si potesse spiegare brevemente le risposte troppo Sarebbe davvero aiutarmi a imparare come funziona tutto questo, e dove sono andato! Sbagliato

Grazie!

. NB: ho cambiato e segnato la linea della mia funzione che il messaggio di errore sta parlando di

L'ho cambiato da:

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

a:

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

Questo è perché voglio alcun tasto annidati nei bambini oggetto di anche essere creati, in modo da screen_name aveva una chiave figli, anche loro sarebbero stati creati. Spiacenti , spero che tu possa capire questo!

Sto guardando http://jsperf.com/create-nested-dom-structure per alcuni indicatori, questo può aiutare anche voi!

È stato utile?

Soluzione

Il "creare" la funzione sta per essere scritta in modo ricorsivo.

Per creare un nodo dai dati (in generale), è necessario:

  1. Trova la proprietà "tag" e creare un nuovo elemento
  2. Dare l'elemento il valore "id" dell'elemento (presa sulla base dei dati)
  3. Per ogni elemento in "figli", fare un nodo e aggiungerla

In questo modo:

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;
}

che restituirà una matrice di elementi del documento creati dall'oggetto originale "specifica". Così dal vostro esempio, che si dice:

var createdNodes = create(nodes);

e "createdNodes" sarebbe un array di un elemento, un tag <article> con ID "tweets". Tale elemento avrebbe avuto due figli, un tag <h2> con ID "SCREEN_NAME" e un tag <p> con id "testo". (Ora che ci penso, si potrebbe desiderare di saltare l'assegnazione "id" a meno che la descrizione nodo ha una voce esplicita "id", o qualcosa del genere).

In questo modo, se si dispone di un <div> nella tua pagina chiamata "tweets" (per usare il tuo esempio, anche se è così che ci si sicuramente vuole tagliare il "id" impostazione parte della mia funzione), si sarebbe aggiungere i risultati in questo modo:

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

for (var eindex = 0; eindex < createdNodes.length; ++eindex)
  tweets.appendChild(createdNodes[eindex]);

Altri suggerimenti

Ho aggiunto una funzione appendList che accetta una lista di elementi, e il contenitore da aggiungere al. Ho rimosso l'accodamento per "tweet" parte dal creare la funzione di separare in modo più efficace il vostro codice.

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")); 

Sulla base della risposta precedente: Penso che è ancora necessario per creare l'elemento che si sta cercando di aggiungere:

  

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

dovrebbe essere

  

tmp.appendChild (document.createElement (bambini [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);  
    };  
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top