problemi a creare nidificato dom nodi in javascript
-
25-09-2019 - |
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!
Soluzione
Il "creare" la funzione sta per essere scritta in modo ricorsivo.
Per creare un nodo dai dati (in generale), è necessario:
- Trova la proprietà "tag" e creare un nuovo elemento
- Dare l'elemento il valore "id" dell'elemento (presa sulla base dei dati)
- 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);
};
};