我很难找到一种优雅有效的方法来处理nodeJS中不规则的嵌套数组/对象。我所说的不规则是指可以具有1、2、3或更大维度的数组/对象。
例如,两种不同的情况:
第一种情况:
"head": {
"firstElement": {
"Choice1": [
"Some text",
"some text"
],
"Choice2": [
"Some text",
"Some text"
]
},
"SecondElement": [
"Some text",
"Some text"
]
}
第二种情况:
"head": {
"firstElement": [
"Some text",
"Some text"
],
"secondElement": [
"Some text",
]
}
我想要的是能够提取所有内容,保留除不需要的所有内容之外的所有内容,最后将其清晰地打印在div中。
预期:
<div>
<h1>FirstElement</h1>
<h2>Choice#</h2>
<p>Some text</p>
<p>Some text</p>
<h1>SecondElement</h1>
<p>Some text</p>
<p>Some text</p>
</div>
HTML中的嵌套方面不是问题,我只是在为算法苦苦挣扎。
答案 0 :(得分:0)
进行任意深度的处理始终是一项艰巨的任务,尤其是当结构(如您的示例)在类型之间可能有所不同时。
要解决这种结构,您可以使用递归模板,该模板将迭代该结构并生成内容或继续扫描到最低级别的子级。
<template name="recursive">
{{#with data}}
{{#if isString this}}
<!--
Print string values directly as paragraph.
No recursion included.
-->
<p>{{this}}</p>
{{else if isArray this}}
<!--
If we have an array f values then iterate
and call a new template instance but don't
increase the level, since the values in the
array could also be just strings
-->
{{#each this}}
{{> recursive data=this level=level}}
{{/each}}
{{else if isObject this}}
<!--
Now with an object we need to transform it into
an iterable version, first (using the mapped helper).
We also need to increase the level of nesting using incLevel.
-->
{{#each map in (mapped this)}}
<!-- this is to keep the code more tidy and readable -->
{{> headline level=level title=map.key}}
{{> recursive data=map.value level=incLevel}}
{{/each}}
{{/if}}
{{/with}}
</template>
出于可读性的考虑,我们可以提取逻辑以确定要渲染到自己的模板中的标题:
<template name="headline">
{{#if level1 level}}
<h1>{{title}}</h1>
{{else if level2 level}}
<h2>{{title}}</h2>
{{else}}
{{level}}
{{/if}}
</template>
阅读模板代码中的注释,以了解其中发生的情况。
现在,由于预期的渲染逻辑的复杂性,我们需要一些辅助工具
Template.recursive.helpers({
mapped (obj) {
return Object.keys(obj).map(key => ({ key, value: obj[ key ] }))
},
level() {
return Template.instance().data.level || 1
},
incLevel() {
const level = Template.instance().data.level
return level ? level + 1 : 2
},
isArray (element) {
return Array.isArray(element)
},
isString (element) {
return typeof element === 'string'
},
isObject (element) {
return typeof element === 'object'
}
})
请注意,级别从1开始,因为您的标题也从1开始。 说到标题,我们还需要标题模板的助手:
Template.headline.helpers({
level1(lvl) {
return lvl === 1
},
level2(lvl) {
return lvl === 2
},
// ... up to 6
// then fallback to <strong> if lvl > 6
})
您可以这样调用模板(请注意,我只是将其放在<body>
中作为示例):
<body>
{{> recursive data=example1}}
{{> recursive data=example2}}
</body>
在example1
和example2
是帮助者的地方,将数据传递到您的模板:
const example1 = {
'head': {
'firstElement': {
'Choice1': [
'Some text',
'some text'
],
'Choice2': [
'Some text',
'Some text'
]
},
'SecondElement': [
'Some text',
'Some text'
]
}
}
const example2 = {
'head': {
'firstElement': [
'Some text',
'Some text'
],
'secondElement': [
'Some text',
]
}
}
Template.body.helpers({
example1() {
return Object.values(example1)
},
example2() {
return Object.values(example2)
}
})
现在您可能想知道为什么我没有包括以下要求:
保留除我不想要的“选择”以外的所有内容
这是因为使用这样的模板,您已经可以完成一项复杂的任务:
将另一种责任压缩到这样的模板中会从字面上炸毁您的代码(在某些时候,我认为您的结构比本示例中的还要复杂)。
那您该怎么解决这个问题?