我有模板,我需要构建html。我可以解析每个元素,但是在尝试构建所有html时卡住了。我的代码暂时无法正常工作。而且可能是我完全错误的方法,它应该是从模板制作html的另一种方法。有人可以帮忙吗?
const data = ['html', [
['head', [
['title', 'titletext'],
]],
['body', { class: 'bodyClass' }, [
['h1', { class: 'headerClass' }, 'h1text'],
['div', [
['span', 'span1text'],
['span', 'span2text'],
]],
]],
]];
const tagBuilder = (tagArray) => {
if (tagArray[1] instanceof Array) {
return tagBuilder(tagArray[1]);
}
if (tagArray[1] instanceof Object) {
return `<${tagArray[0]} class="${tagArray[1].class}">` + String(tagArray[2]) + `</${tagArray[0]}>`;
}
return `<${tagArray[0]}>` + String(tagArray[1]) + `</${tagArray[0]}>`;
}
const htmpBuilder = (data) => {
return data.map(element => tagBuilder(element));
};
document.getElementById("output").textContent = htmpBuilder(data);
<pre id="output">
</pre>
我需要的输出:
<html>
<head>
<title>titletext</title>
</head>
<body class="bodyClass">
<h1 class="headerClass">h1text</h1>
<div>
<span>span1text</span>
<span>span2text</span>
</div>
</body>
</html>
You might consider creating a structure with objects instead - that way, you can just look up the .class
property of the object, or the .contents
property of the object, or the .tag
property of the object, the process will probably make a whole lot more sense at a glance. The only real non-trivial logic involved is checking if the .contents
is an array (in which case, recursively .map
them by tagBuilder
and join by the empty string):
const data = {
tag: 'html',
contents: [
{
tag: 'head',
contents: [{
tag: 'title',
contents: 'titletext'
}]
}, {
tag: 'body',
class: 'bodyClass',
contents: [{
tag: 'h1',
class: 'headerClass',
contents: 'h1text'
}, {
tag: 'div',
contents: [{
tag: 'span',
contents: 'span1text'
}, {
tag: 'span',
contents: 'span2text'
}]
}]
}
]
};
const tagBuilder = ({ tag, class: className, contents = '' }) => {
const contentsStr = Array.isArray(contents)
? contents.map(tagBuilder).join('')
: contents;
return `<${tag}${className ? ` class="${className}"` : ''}>${contentsStr}</${tag}>`;
}
console.log(tagBuilder(data));
If you need newlines between tags and pretty-printed HTML too (which usually shouldn't matter), then pass along an indent
parameter too, which gets added to the start of tag lines (and the start of end-tag lines, when that tag contains non-text children):
const data = {
tag: 'html',
contents: [
{
tag: 'head',
contents: [{
tag: 'title',
contents: 'titletext'
}]
}, {
tag: 'body',
class: 'bodyClass',
contents: [{
tag: 'h1',
class: 'headerClass',
contents: 'h1text'
}, {
tag: 'div',
contents: [{
tag: 'span',
contents: 'span1text'
}, {
tag: 'span',
contents: 'span2text'
}]
}]
}
]
};
const tagBuilder = ({ tag, class: className, contents = '' }, indent = 0) => {
const contentsStr = Array.isArray(contents)
? '\n' + contents.map(item => ' '.repeat(indent + 2) + tagBuilder(item, indent + 2)).join('\n') + '\n'
: contents;
return `<${tag}${className ? ` class="${className}"` : ''}>${contentsStr}${Array.isArray(contents) ? ' '.repeat(indent) : ''}</${tag}>`;
}
console.log(tagBuilder(data));
如果必须使用原始data
结构(由于逻辑混乱,我会认为这是一个错误),然后从数组中提取标记,内容和className,然后执行完全相同的操作:
const data = ['html', [
['head', [
['title', 'titletext'],
]],
['body', { class: 'bodyClass' }, [
['h1', { class: 'headerClass' }, 'h1text'],
['div', [
['span', 'span1text'],
['span', 'span2text'],
]],
]],
]];
const tagBuilder = (arr, indent = 0) => {
const tag = arr.shift();
const className = !Array.isArray(arr[0]) && typeof arr[0] === 'object'
? arr.shift().class
: '';
const contents = arr.length
? arr.shift()
: '';
const contentsStr = Array.isArray(contents)
? '\n' + contents.map(item => ' '.repeat(indent + 2) + tagBuilder(item, indent + 2)).join('\n') + '\n'
: contents;
return `<${tag}${className ? ` class="${className}"` : ''}>${contentsStr}${Array.isArray(contents) ? ' '.repeat(indent) : ''}</${tag}>`;
}
console.log(tagBuilder(data));
感谢您的帮助。您的模板看起来更有用,但是现在我们有了。(并且我需要从具有这种结构的模板构建html。
好吧,您确实说过“而且我可能全都错了”-试图从这样一个怪异的结构构造HTML 是一件很奇怪的事情,我会考虑必须首先使用这样的结构来成为大问题之一。您仍然可以测试并从数组中提取参数的类型,然后使用与以前相同的逻辑,但是IMO看起来非常难看
您说的这是“怪异的结构”。:( 谢谢你的帮助!