Javascript 在循环中附加HTML元素

Javascript 在循环中附加HTML元素,javascript,recursion,dom,Javascript,Recursion,Dom,给定如下JSON结构: [ "Hi, ", { "tag": "a", "attr": { "href": "https://example.com", "target": "_blank" }, "body": [ "click ", { "tag": "strong", "body": [ "here " ] } ]

给定如下JSON结构:

[
"Hi, ",
  {
    "tag": "a",
    "attr": {
      "href": "https://example.com",
      "target": "_blank"
    },
    "body": [
      "click ",
      {
        "tag": "strong",
        "body": [
          "here "
        ]
      }
    ]
  },
  "to get ",
  {
    "tag": "em",
    "body": [
      "amazing "
    ]
  },
  "offers."
]  
我试图迭代它,将值转换为HTML标记。使用上面的JSON,我希望构建以下内容:

<span>Hi, </span><a href="https://google.com" target="_blank">click <strong>here</strong></a>to get <em>amazing </em><span>offers.</span>
其中buildElement是一种方便的方法,用于创建节点、设置属性并附加任何文本节点:

 buildElement(tag, attributes, value = '') {
        let node = document.createElement(tag);
        if (value) {
            let text = document.createTextNode(value);
            node.appendChild(text);
        }
        if (attributes.length === 0) {
            return node;
        }
        return this.setAttributes(node, attributes);
    }
我遇到的问题是,即使在调试时,我看到“strong”节点被传递给parentNode.appendChild(childNode),当返回值时,parentNode“a”标记没有子“strong”,给我这样的结果:

<span>Hi, </span><a href="https://google.com" target="_blank">click </a><span>to get </span><em>amazing </em><span>offers.</span>
Hi,获得令人惊叹的优惠。

这显然是缺乏“a”标签内的“强”标签。为什么没有将节点附加到父节点?

问题似乎在于,在正文中同时存在纯文本和附加节点的情况下,第二个映射函数实际上生成了两个节点

由于第一次迭代只包含文本节点,因此获得第二次完整迭代的方法是将映射结果传递给变量,然后返回数组中的最后一个索引,如下所示:

 stringHtmlText(content) {
    {
        return content.map(tranche => {
            if (typeof tranche === "object") {
                let attrs = [];
                for (let attr in tranche.attr) {
                    if (tranche.attr.hasOwnProperty(attr)) {
                        let thisAttr = {};
                        thisAttr[attr] = tranche.attr[attr];
                        attrs.push(thisAttr);
                    }
                }
                let parentNode;
//Assign to variable
                let trancher = tranche.body.map(entry => {
                    if (typeof entry === "object") {
                        let childNode = this.stringHtmlText([entry]);
                        if (Array.isArray(childNode)) {
                            childNode = childNode[0];
                        }
                        parentNode.appendChild(childNode);
                        return parentNode;
                    } else {
                        parentNode = this.buildElement(tranche.tag, attrs, entry);
                        return parentNode;
                    }
                });
// Return only the last, complete node

                return trancher[(trancher.length - 1)]

            } else {
                return this.buildElement('span', [], tranche);
            }

        });
    }
}
 stringHtmlText(content) {
    {
        return content.map(tranche => {
            if (typeof tranche === "object") {
                let attrs = [];
                for (let attr in tranche.attr) {
                    if (tranche.attr.hasOwnProperty(attr)) {
                        let thisAttr = {};
                        thisAttr[attr] = tranche.attr[attr];
                        attrs.push(thisAttr);
                    }
                }
                let parentNode;
//Assign to variable
                let trancher = tranche.body.map(entry => {
                    if (typeof entry === "object") {
                        let childNode = this.stringHtmlText([entry]);
                        if (Array.isArray(childNode)) {
                            childNode = childNode[0];
                        }
                        parentNode.appendChild(childNode);
                        return parentNode;
                    } else {
                        parentNode = this.buildElement(tranche.tag, attrs, entry);
                        return parentNode;
                    }
                });
// Return only the last, complete node

                return trancher[(trancher.length - 1)]

            } else {
                return this.buildElement('span', [], tranche);
            }

        });
    }
}