javascript - 将嵌套数组转换为 HTML 结构

标签 javascript arrays recursion mapreduce reduce

我几天来一直在思考这个“简单”的练习,但确实陷入了困境。这真的让我抓狂了。 我需要将嵌套数组转换为 HTML。下面是一个数组的示例:

const data = ['html', [
  ['head', [
    ['title', 'Your title text goes here'],
  ]],
  ['body', { class: 'container' }, [
    ['h1', { class: 'header' }, 'h1 text'],
    ['div', [
      ['span', 'span text2'],
      ['span', 'span text3'],
    ]],
  ]],
]];

预期的结果应该是这样的:

<html>
  <head>
    <title>your title text</title>
  </head>
  <body class="container">
    <h1 class="header">h1 text</h1>
    <div>
      <span>span text2</span>
      <span>span text3</span>
    </div>
  </body>
</html>

我从一个辅助函数开始(从数组创建每个标签),现在的样子如下:

const tagBuilder = (arr) => {
  console.log(arr)
  // ['div']; ==> <div></div>
  if(arr.length === 1) {
    return `<${arr[0]}></${arr[0]}>`
  }
  // Maximum length of the pure array (without nested children) is - 3
  return arr.length === 3
  // ['h1', { class: 'header' }, 'html builder example']
  ? `<${arr[0]} class="${arr[1].class}">${arr[2]}</${arr[0]}>`
  // ['h1', { class: 'header' }]
  : arr.length === 2 && typeof arr[1] === 'object'
  ? `<${arr[0]} class="${arr[1].class}"></${arr[0]}>`
  // ['h1', 'header - text']
  : `<${arr[0]}>${arr[1]}</${arr[0]}>`
}

到目前为止,一切正常。当我尝试创建实际的 HTML 构建器函数时,棘手的部分就开始了。我想迭代数组的每个元素,检查它是否有嵌套元素(子元素),保存指定的标签,然后继续深入。

const buildHTML = (array) => {
  let acc = ""
  const iterator = (arr) => {
    for(const el of arr) {
     
    }
  }
  iterator(array)
  return acc;
}

到目前为止,我可以在没有嵌套数组的情况下迭代并保存 HTML 结构,但当数组有子元素时,它就会中断。我正在尝试“减少”和嵌套“ map ”,但没有运气。您能否指出解决方案或正确的探索方法?我的猜测是最终的函数应该如下所示:

const textAndArrChild = ['div',
['span', 'span text3']];
// <div><span>span text3</span></div>

const tagBuilder = (arr) => {
  // ['div']; ==> <div></div>
  if(arr.length === 1) {
    return `<${arr[0]}></${arr[0]}>`
  }
  // Maximum length of the pure array (without nested children) is - 3
  return arr.length === 3
  // ['h1', { class: 'header' }, 'html builder example']
  ? `<${arr[0]} class="${arr[1].class}">${arr[2]}</${arr[0]}>`
  // ['h1', { class: 'header' }]
  : arr.length === 2 && typeof arr[1] === 'object'
  ? `<${arr[0]} class="${arr[1].class}"></${arr[0]}>`
  // ['h1', 'header - text']
  : `<${arr[0]}>${arr[1]}</${arr[0]}>`
}

const buildHTML = (array) => {
  return array.reduce((acc, el, index, arr) => {
    if(typeof el === 'string' && Array.isArray(arr[index + 1])) {
      acc = tagBuilder([el]);
      // return acc += el.map(buildHTML) // TODO cause error
      // need to iterate through the nested array
    } else {
      // insert pure tags from an array into the acc
    }
    
    return acc;
  }, "")
}



console.log(buildHTML(textAndArrChild))

最佳答案

⚠️
⚠️⚠️
⚠️⚠️⚠️

除非这是一个练习否则你永远不应该以这种方式生成 HTML!这是一个巨大的安全风险。考虑使用默认进行编码/转义的模板库,例如 .

⚠️⚠️⚠️
⚠️⚠️
⚠️


如果您愿意更改表示标签的数据结构,则可以使此过程变得更容易:

[tag-name tag-attribute children*]

其中子级是字符串或另一个标记数据结构。示例:

  ['html', {},
    ['head', {},
      ['title', {}, 'Your title text goes here']],
    ['body', { class: 'container' },
      ['h1', { class: 'header' }, 'h1 text'],
      ['div', {},
        ['span', {}, 'span text2'],
        ['span', {}, 'span text3']]]]

我们将子项周围不必要的包装器 [] 换成了强制属性参数,如果不需要,该属性参数只是 {}。恕我直言,还不错。

如果我们坚持这个约定,我们可以声明一个 tag 函数,如下所示:

const tag = (name, attr, ...children) => {
  // ...
};

因为我们将有嵌套标签,生成完整标记的自然解决方案是使用递归:

const tag = (name, attr, ...children) => `
  <${name} ${Object.entries(attr).map(([n, v]) => `${n}="${v}"`).join(' ')}>
    ${children.map(child => typeof child === 'string' ? child : tag(...child)).join("\n")}
  </${name}>
`;

console.log(tag(...markup))
<script>
const markup =
  ['html', {},
    ['head', {},
      ['title', {}, 'Your title text goes here']],
    ['body', { class: 'container' },
      ['h1', { class: 'header' }, 'h1 text'],
      ['div', {},
        ['span', {}, 'span text2'],
        ['span', {}, 'span text3']]]];
</script>

关于javascript - 将嵌套数组转换为 HTML 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64544789/

相关文章:

javascript - 如何使两个图像等高并保持调整大小

javascript - 编写一个 javascript 乘法函数,它将返回两个单独的结果

parsing - 'not' 的 lisp 解析

php - 递归要求所有文件

python - 递归函数调用

javascript - 在同构 React Web 应用程序中有选择地进行服务器渲染的最佳方式是什么?

javascript - Angular JS Amcharts 指令

javascript - 半屏侧边栏修正

arrays - 如何循环查看命令的输出?

php - 数组循环假设为零数据?