#javascript #typescript #algorithm
#javascript #typescript #алгоритм
Вопрос:
Я работаю над dynamic form builder, где у меня есть элементы формы внутри структуры сетки строк / столбцов, каждый из моих элементов формы (object) имеет специальный ключ с именем model, который определяет имя поля и ключ значения, который определяет его значение. У меня снова есть вложенная форма, которая делает то же самое, мне нужно извлечь эти модель и значения и сделать их объектом, в случае повторителя формы это будет массив. Вот примерный формат данных моей формы:
[
{
"component":"row",
"attrs":{
"child_components":[
{
"component":"column",
"attrs":{
"child_components":[
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"first_name",
"value":"",
}
},
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"last_name",
"value":"",
}
}
]
}
},
{
"component":"column",
"attrs":{
"child_components":[
{
"component":"form-repeater",
"attrs":{
"child_components":[
{
"component":"column",
"attrs":{
"child_components":[
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"name",
"value": ""
}
},
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"url",
"value":""
}
}
]
}
},
{
"component":"column",
"attrs":{
"child_components":[
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"name",
"value":""
}
},
{
"component":"input-text",
"attrs":{
"child_components":[
],
"model":"url",
"value":""
}
}
]
}
}
],
"model":"links",
"value":""
}
}
]
}
}
]
}
}
]
Для выполнения этого я пытаюсь создать рекурсивную функцию:
findModel(ele) {
ele.forEach((element) => {
if(typeof element.attrs.model !== 'undefined') {
if(element.component === 'form-repeater') {
let repeater = [];
element.attrs.child_components.forEach((rep) => {
let data = this.findModel(rep.attrs.child_components);
repeater.push(data);
})
const repeaterData = {}
repeaterData[element.attrs.model] = repeater;
return repeaterData;
}
else {
const data = {}
data[element.attrs.model] = element.attrs.value;
return data;
}
}
else {
if(typeof element.attrs.child_components !== 'undefined' amp;amp; element.attrs.child_components.length) {
return this.findModel(element.attrs.child_components);
}
}
})
},
И я вызываю эту функцию:
let data = findModel(form_data)
console.log(data)
//Always comes undefined.
Мой окончательный формат данных будет выглядеть примерно так, чего я не могу достичь:
{
first_name: '',
last_name: '',
links: [
{name: '', url: ''},
{name: '', url: ''}
]
}
Помогите мне в достижении вышеуказанного формата. Любой лучший подход к этому приветствуется. Спасибо.
Комментарии:
1. Рекурсия — правильный подход. Код мог бы быть немного чище, но это не так уж плохо
2. В чем ваш вопрос? Если вы ищете предложения по обзору кода и улучшению, то вы, вероятно, захотите codereview.stackexchange.com
3. @mbdavis мой код не работает. Нужна помощь в получении желаемого формата.
4. @AluanHaddad Ты можешь мне помочь?
5. @AluanHaddad Функция рекурсии не работает, она всегда выбрасывает
undefined
набор данных. Я виноват, если вы ошиблись.
Ответ №1:
Ваша функция возвращает, undefined
потому что у нее нет return
инструкции. return
Инструкции, которые у вас есть, возвращаются из forEach
обратного вызова, который (очевидно) не является той же функцией.
Возврат значения в forEach
обратном вызове бесполезен, поскольку это значение исчезает в забвении. forEach
Не предназначен для этого.
Вам необходимо:
- используйте
.map
вместо.forEach
- возвращает результат
.map
Итак:
return ele.map((element) => {
Наконец, в вашей логике обратного вызова есть случай, когда вы не возвращаете значение: у внешнего else
блока есть return
внутри if
блока, но нет return
инструкции, когда это внутреннее if
условие не выполняется. Таким образом, существует теоретическая возможность того, что обратный вызов в некоторых случаях вернет undefined, что означает, что .map
вернет массив с потенциальным неопределенным элементом.
Вы должны убедиться, что все обращения в коде обратного вызова приводят к контролируемому return
.