我有一个函数将对象作为参数,并使用对象的结构来创建嵌套的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的一些指示,这对你也有帮助!
答案 0 :(得分:2)
您的“创建”功能必须以递归方式编写。
要从您的数据创建节点(通常),您需要:
因此:
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”将是一个元素的数组,<article>
标记,ID为“tweets”。该元素将包含两个子元素,<h2>
标记为id“screen_name”,<p>
标记为id“text”。 (现在我想起来了,除非节点描述有明确的“id”条目,否则你可能想跳过“id”赋值。)
因此,如果您的页面中有<div>
,称为“推文”(使用您的示例,但如果是这样,您肯定想要删除我的功能中的“id”设置部分),那么'' d添加如下结果:
var createdNodes = create(nodes), tweets = document.getElementById('tweets');
for (var eindex = 0; eindex < createdNodes.length; ++eindex)
tweets.appendChild(createdNodes[eindex]);
答案 1 :(得分:0)
我添加了一个函数appendList,它接受一个元素列表和要追加的容器。我从create函数中删除了“tweets”部分的附加内容,以便更有效地分离代码。
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"));
答案 2 :(得分:-1)
以前一个答案为基础: 我认为你仍然需要创建你想要追加的元素:
tmp.appendChild(儿童[丙] .TAG);
应该是
tmp.appendChild(使用document.createElement(儿童[丙] .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);
};
};