在 javascript 中创建嵌套 dom 节点时遇到问题

发布于 2024-10-02 23:09:23 字数 1672 浏览 6 评论 0原文

我有一个函数,它接受一个对象作为参数,并使用该对象的结构来创建嵌套的 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 等。

不过,任何 hel 将不胜感激请:我确信框架或库只需几行代码或类似的代码即可为我完成此操作,但我不想使用它们对于这个特定的项目。

如果您也能简要解释一下您的答案,那将真正帮助我了解这一切是如何运作的以及我哪里出错了!

谢谢你!

注意:我已经更改并标记了函数中错误消息所涉及的行。

我将其从: 更改

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

为:

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

这是因为我希望也创建子对象中的任何嵌套键,因此 screen_name 有一个子键,它们也会被创建。 抱歉,希望您能理解!

我正在查看 http://jsperf.com/create-nested-dom-struct 对于一些提示,这也可能对您有帮助!

I've a function that takes an object as a parameter, and uses the structure of the object to create nested DOM nodes, but I receive the following error:

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.

What I would like my function to do, is, when supplied with a suitable object as a parameter, example:

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

It would create the following DOM nodes:

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

Here is my attempt so far:

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

I'm already struggling!

Ideally I'd like to eventually add more child key's to each object, not just tag, but also id, innerHTML, class etc.

Any hel would be much appreciated, though please: I'm sure a framework or library could do this for me in just a few lines of code, or something similar, but I'd prefer not to use one for this particular project.

If you could briefly explain your answers too it'd really help me learn how this all works, and where I went wrong!

Thank you!

NB: I've changed and marked the line in my function that the error message is talking about.

I changed it from:

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

to:

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

This is because I want any nested keys in the children object to also be created, so screen_name had a children key, they too would be created. Sorry, I hope you can understand this!

I'm looking at http://jsperf.com/create-nested-dom-structure for some pointers, this may help you too!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遗心遗梦遗幸福 2024-10-09 23:09:23

您的“创建”函数必须递归编写。

要从数据创建节点(通常),您需要:

  1. 找到“tag”属性并创建一个新元素
  2. 为该元素提供该元素的“id”值(从数据中获取)
  3. 对于“children”中的每个元素",创建一个节点并附加它

因此:

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”将是一个元素的数组,即一个 id 为“tweets”的

标记。该元素将有两个子元素,一个 id 为“screen_name”的

标记和一个 id 为“text”的

标记。 (现在我想起来了,您可能想跳过“id”分配,除非节点描述有明确的“id”条目或其他内容。)

因此,如果您有一个

在名为“tweets”的页面中(使用您的示例,但如果是这样,您肯定想删除我的函数的“id”设置部分),您将添加如下结果:

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

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

Your "create" function is going to have to be written recursively.

To create a node from your data (in general), you need to:

  1. Find the "tag" property and create a new element
  2. Give the element the "id" value of the element (taken from the data)
  3. For each element in "children", make a node and append it

Thus:

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

That will return an array of document elements created from the original "specification" object. Thus from your example, you'd call:

var createdNodes = create(nodes);

and "createdNodes" would be an array of one element, an <article> tag with id "tweets". That element would have two children, an <h2> tag with id "screen_name" and a <p> tag with id "text". (Now that I think of it, you might want to skip the "id" assignment unless the node description has an explicit "id" entry, or something.)

Thus if you have a <div> in your page called "tweets" (to use your example, though if so you'd definitely want to cut out the "id" setting part of my function), you'd add the results like this:

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

for (var eindex = 0; eindex < createdNodes.length; ++eindex)
  tweets.appendChild(createdNodes[eindex]);
守望孤独 2024-10-09 23:09:23

我添加了一个函数appendList,它接受元素列表以及要附加到的容器。我从创建函数中删除了“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")); 

I added a function appendList that accepts a list of elements, and the container to append to. I removed the append to "tweets" part out of the create function to more effectively separate your 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")); 
樱娆 2024-10-09 23:09:23

基于之前的答案:
我认为您仍然需要创建要附加的元素:

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

应该是

tmp.appendChild(document.createElement(children[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);  
    };  
};

Building on the previous answer:
I think you still need to create the element you're trying to append:

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

should be

tmp.appendChild(document.createElement(children[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);  
    };  
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文