difficulté à créer des noeuds dom imbriqués en javascript
-
25-09-2019 - |
Question
I ai une fonction qui prend un objet en tant que paramètre, et utilise la structure de l'objet à créer des noeuds DOM imbriqués, mais je reçois l'erreur suivante:
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.
Ce que je voudrais que ma fonction à faire, est, lorsqu'il est fourni avec un objet approprié comme paramètre, par exemple:
var nodes = {
tweet: {
children: {
screen_name: {
tag: "h2"
},
text: {
tag: "p"
}
},
tag: "article"
}
};
Il créerait les noeuds DOM suivants:
<article>
<h2></h2>
<p></p>
</article>
Voici ma tentative à ce jour:
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);
};
};
Je suis déjà aux prises!
Idéalement, je voudrais éventuellement ajouter la clé de l'enfant de chaque objet, non seulement tag
, mais aussi id, innerHTML, class
etc.
Tout hel serait très apprécié, mais s'il vous plaît: Je suis sûr un cadre ou à la bibliothèque pourrait faire cela pour moi en seulement quelques lignes de code, ou quelque chose de similaire, mais I « d préfère ne pas utiliser un pour ce projet particulier.
Si vous pouviez expliquer brièvement vos réponses aussi que ça m'a vraiment aider à apprendre comment tout cela fonctionne, et où je suis allé mal!
Merci!
NB: Je l'ai changé et a marqué la ligne dans ma fonction que le message d'erreur parle de
.Je l'ai changé à partir de:
mp.appendChild(obj[i].children);
à:
mp.appendChild(create(obj[i].children));
Ceci est parce que je veux toutes les clés imbriquées dans les enfants objet aussi être créé, si screen_name
avait une clé pour les enfants, ils seraient également créés. Désolé , je l'espère, vous pouvez comprendre!
Je regarde http://jsperf.com/create-nested-dom-structure pour quelques conseils, cela peut vous aider!
La solution
Votre « créer » la fonction va être écrit de manière récursive.
Pour créer un noeud à partir de vos données (en général), vous devez:
- Trouvez la propriété « tag » et créer un nouvel élément
- donner à l'élément la valeur « id » de l'élément (pris à partir des données)
- Pour chaque élément « enfants », faire un nœud et l'ajouter
Ainsi:
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;
}
Cela renvoie un tableau d'éléments de documents créés à partir de l'objet « spécification » d'origine. Ainsi, à partir de votre exemple, vous appelez:
var createdNodes = create(nodes);
et « createdNodes » serait un tableau d'un élément, une balise <article>
avec id « tweets ». Cet élément aurait deux enfants, une étiquette <h2>
avec id « screen_name » et une étiquette de <p>
avec id « texte ». (Maintenant que je pense, vous pouvez sauter l'affectation « id » à moins que la description du noeud a une entrée explicite « id », ou quelque chose.)
Ainsi, si vous avez un <div>
dans votre page appelée « tweets » (pour utiliser votre exemple, mais si donc vous voudriez certainement découper le paramètre « id » partie de ma fonction), vous ajouteriez les résultats comme ceci:
var createdNodes = create(nodes), tweets = document.getElementById('tweets');
for (var eindex = 0; eindex < createdNodes.length; ++eindex)
tweets.appendChild(createdNodes[eindex]);
Autres conseils
I ajouté un appendList de fonction qui accepte une liste d'éléments, et le récipient à ajouter à. J'ai enlevé le append à « tweets » partie de la fonction créer pour séparer plus efficacement votre code.
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"));
Miser sur la réponse précédente: Je pense que vous avez encore besoin de créer l'élément que vous essayez d'ajouter:
tmp.appendChild (enfants [prop] .tag);
doit être
tmp.appendChild (document.createElement (enfants [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);
};
};