Работа с произвольными уровнями глубины всегда является сложной задачей, особенно когда структура (как в ваших примерах) может дополнительно варьироваться между типами.
Чтобы справиться с такой структурой, вы можете использовать рекурсивный шаблон, который выполняет итерацию структуры и либо генерирует контент, либо продолжает сканировать до самого нижнего уровня дочерних элементов.
<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'
}
})
Обратите внимание, что уровни начинаются с одного, потому что ваши заголовки также начинаются с одного.
Говоря о заголовках, нам также нужны помощники для заголовка. Шаблон:
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)
}
})
Теперь вы можете удивиться, почему я не включил следующее требование:
оставь все, кроме "Выборов", которые мне не нужны
Это потому, что с таким шаблоном вы уже выполнили сложную задачу:
- обнаружить структуру
- решить, как отображать содержимое
- визуализация контента
Внедрение еще одной ответственности в такой шаблон буквально взорвет ваш код (в какой-то момент я предполагаю, что ваши структуры будут еще более сложными, чем в этом примере).
Так что вы могли бы сделать, чтобы решить эту проблему?
- Убедитесь, что вы передаете данные только в шаблон, который будет обработан
- Пусть «родительский» шаблон обрабатывает обработку (удаляя нежелательные варианты выбора), что в основном является задачей, которую можно выполнить без Blaze, поскольку он в основном состоит из поиска и фильтрации.
- Не допускайте в этот шаблон ничего, что выходит за рамки рендеринга некоторых данных.
- Если проблемы все еще возникают или возникают проблемы с этим инкапсулированным подходом, пожалуйста, пересмотрите вложенную природу исходных данных. Возможно, вы можете нормализовать вещи, чтобы получить более линейные структурированные данные.