几天来,我一直在考虑这个“简单”的练习,结果被困住了。我都快疯了。我需要将嵌套数组转换为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>
我已经从一个helper函数开始(从数组创建每个标记),下面是它现在的样子:
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结构,但是当数组有子组时,它就会中断。我尝试“减少”和嵌套“地图”,但没有运气。你能给我指出解决办法或正确的探索方式吗?我的猜测是,最终的函数应该是这样的:
null
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))
null
你可以让它变得更简单。如果我们不考虑格式化缩进,它可能是这样的。
null
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'],
]],
]],
]];
const render = data =>{
let tag, attributes, childrens;
if(data.length === 2){
[tag, childrens] = data;
} else if(data.length === 3){
[tag, attributes, childrens] = data;
}
let attrStr = ""
for(let attr in attributes){
attrStr += " " + attr + '="' + attributes[attr] + '"';
}
let childrenStr = ""
if(typeof childrens !== "string"){
for(let children of childrens){
childrenStr += render(children);
}
} else {
childrenStr = childrens;
}
return (`<${tag}${attrStr}>${childrenStr}</${tag}>`)
}
console.log(render(data))