Проблемы с созданием узлов вложенных DOM в JavaScript
-
25-09-2019 - |
Вопрос
У меня функция, которая принимает объект в качестве параметра, и использует структуру объекта для создания узлов вложенных 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
и т.п.
Любой Хэл будет очень признателен, хотя, пожалуйста: я уверен Рамки или библиотека мог сделать это для меня всего за несколько строк кода, или что-то подобное, но Я бы предпочел не использовать один Для этого конкретного проекта.
Если бы вы могли кратко объяснить свои ответы, это действительно помогло мне узнать, как это все работает, а где я пошел не так!
Спасибо!
NB: Я изменился и пометил линию в моей функции, о котором говорится сообщение об ошибке.
Я изменил это из:
mp.appendChild(obj[i].children);
к:
mp.appendChild(create(obj[i].children));
Это потому, что я хочу, чтобы любые вложенные ключи в детском объекте также будут созданы, так screen_name
У детского ключа они тоже будут созданы. Извиняюсь, Надеюсь, вы можете понять это!
Я смотрю на http://jsperf.com/create-nested-dom-structure. Для некоторых указателей это может помочь вам тоже!
Решение
Ваша функция «Создание» должна быть написана рекурсивно.
Чтобы создать узел из ваших данных (в целом), вам нужно:
- Найдите свойство «тега» и создайте новый элемент
- Дайте элемент «ID» значение элемента (взято из данных)
- Для каждого элемента в «детях», сделайте узел и добавьте его
Таким образом:
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);
и «созданныеноды» будут массивом одного элемента, <article>
Тег с идентификатором "твиты". Этот элемент будет иметь два детей, <h2>
Тег с идентификатором "Screen_name" и <p>
Тег с идентификатором "текстом". (Теперь, когда я думаю об этом, вы можете пропустить задание «ID», если узел описание не имеет явного «идентификатора» или что-то еще.)
Таким образом, если у вас есть <div>
На вашей странице под названием «Tweets» (чтобы использовать ваш пример, хотя, если, да, если вам определенно вы должны выбрать «ID» настроить часть моей функции), вы бы добавили такие результаты:
var createdNodes = create(nodes), tweets = document.getElementById('tweets');
for (var eindex = 0; eindex < createdNodes.length; ++eindex)
tweets.appendChild(createdNodes[eindex]);
Другие советы
Я добавил функцию приложения, который принимает список элементов и контейнера для добавления к. Я удалил приложение к «Tweath», из-за функции создания, чтобы более эффективно отделить ваш код.
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"));
Здание на предыдущем ответе: я думаю, что вам все еще нужно создать элемент, который вы пытаетесь добавить:
tmp.appendChild (дети [опоры] .tag);
должно быть
TMP.appendChild (Document.Createlement (дети [опоры] .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);
};
};