我想以編程方式基于背景關系物件構建動態 資料物件,如下例所示。
const context = {
...other props...,
groups: [
{
heading: 'basic',
canHaveMultiple: false, // data.basic = {username: { type: 'text', value: '' }, password: { type: 'password', value: ''}}
inputs: [
{
name: 'username',
type: 'text',
placeholder: 'username',
},
{
name: 'password',
type: 'password',
placeholder: 'password',
},
],
},
{
heading: 'about',
canHaveMultiple: false, // data.about = {about: { type: 'textarea', value: '' }}
inputs: [
{
name: 'about',
type: 'textarea',
placeholder: 'about',
canHaveMultiple: false,
},
],
},
{
heading: 'hobbies',
canHaveMultiple: true, // data.hobbies = { model: { title: {type: 'text', value: ''}, description: {type: 'textarea', value: ''} }, values: [ { title: {type: 'text', value: ''}, description: {type: 'textarea', value: ''} }]
inputs: [
{
name: 'title',
type: 'text',
placeholder: 'about',
canHaveMultiple: false,
},
{
name: 'description',
type: 'description',
placeholder: null,
canHaveMultiple: false,
},
],
},
{
heading: 'friends',
canHaveMultiple: true, // data.friends = { model: {title: {type: 'text', value: '' }, description: { type: 'textarea', value: '' }} }, values: [{ name: {type: 'text', value: ''},hobbies: [{ title: {type: 'text', value: ''}, description: {type: 'textarea', value: ''}} }] }
inputs: [
{
name: 'name',
type: 'text',
placeholder: 'this is fine',
canHaveMultiple: false
},
{
name: 'hobbies',
type: 'nested',
canHaveMultiple: true,
inputs: [
{
name: 'title',
type: 'textarea',
placeholder: 'about',
canHaveMultiple: false,
},
{
name: 'description',
type: 'textarea',
placeholder: 'about',
canHaveMultiple: false,
},
]
}
],
},
],
}
輸出資料應該是這樣的:
data: {
basic: {
username: {
type: 'text',
value: '',
},
password: {
type: 'password',
value: ''
}
},
about: {
about: {
type: 'textarea',
value: '',
}
},
hobbies: {
model: {
title: {
type: 'text',
value: '',
},
description: {
type: 'textarea',
value: '',
}
},
values: [
{
title: {
type: 'text',
value: '',
},
description: {
type: 'textarea',
value: '',
}
}
]
},
friends: {
model: {
name: {
type: 'text',
value: '',
},
hobbies: {
title: {
type: 'text',
value: '',
},
description: {
type: 'textarea',
value: '',
}
}
},
values: [
]
},
}
在本質上,
- groups[ int ].heading 成為資料物件的頂級屬性,并且
- 每個組以及來自輸入的每個子項都有一個canHaveMultiple屬性,用于區分生成的物件結構是否為:
canHaveMultiple == 假
group.input.name: {
group.type,
value: ''
}
或者
canHaveMultiple == 真
{
model: {
group.input.name: {
type: group.input.type,
value: ''
},
... etc
},
values: [{
group.input[0].name: {
type: group.input[0].type,
value: '',
},
group.input[1].name: {
type: group.input[1].type,
value: '',
}
}]
}
該模型在那里,以便我可以輕松地將該物件的新副本推送到值陣列中。
所以這是我的問題:
有沒有辦法遞回地執行此操作,以便程式從背景關系物件創建資料物件,并繼續向下查找任何“嵌套”型別(也在輸入陣列中)的背景關系物件鏈,直到沒有剩余?這是可行且有效的還是我在思考和解決這個問題的方式是錯誤的?
*PS:幾天來,我一直在努力嘗試并為此絞盡腦汁,但我似乎無法讓它適用于超過 3 層的嵌套物件,因為我是遞回的新手。請幫我 :(
uj5u.com熱心網友回復:
該函式首先按標題分組(使用reduce),然后遞回遍歷inputs欄位。也就是說,如果輸入也inputs讓我們回圈它。
const context={groups:[{heading:"basic",canHaveMultiple:!1,inputs:[{name:"username",type:"text",placeholder:"username"},{name:"password",type:"password",placeholder:"password"},]},{heading:"about",canHaveMultiple:!1,inputs:[{name:"about",type:"textarea",placeholder:"about",canHaveMultiple:!1},]},{heading:"hobbies",canHaveMultiple:!0,inputs:[{name:"title",type:"text",placeholder:"about",canHaveMultiple:!1},{name:"description",type:"textarea",placeholder:null,canHaveMultiple:!1},]},{heading:"friends",canHaveMultiple:!0,inputs:[{name:"name",type:"text",placeholder:"this is fine",canHaveMultiple:!1},{name:"hobbies",type:"nested",canHaveMultiple:!0,inputs:[{name:"title",type:"textarea",placeholder:"about",canHaveMultiple:!1},{name:"description",type:"textarea",placeholder:"about",canHaveMultiple:!1},]}]},]}
function transform(arr) {
var result = arr.reduce(function(agg, item) {
var heading = item.heading
var canHaveMultiple = item.canHaveMultiple
var parent;
agg[heading] = {}
if (canHaveMultiple === false) {
parent = agg[heading]
}
if (canHaveMultiple === true) {
agg[heading] = {
model: {},
values: []
}
parent = agg[heading]['model']
}
function do_inputs(parent, inputs) {
inputs.forEach(function(input) {
if (!input.inputs) {
parent[input.name] = {
type: input.type,
value: ''
// todo: placeholder and other properties
}
} else {
// nested
parent[input.name] = {}
do_inputs(parent[input.name], input.inputs)
}
})
}
do_inputs(parent, item.inputs)
return agg;
}, {})
return result;
}
console.log(transform(context.groups));
.as-console-wrapper {
max-height: 100% !important;
}
uj5u.com熱心網友回復:
我有兩個片段可能會讓你大部分時間到達那里。
第一個可能太簡單了,忽略了你的model/value部分。但是應該很容易理解:
const convert = (xs) => Object .fromEntries (
xs .map (({name, type, inputs = []}) =>
[name, inputs .length ? convert (inputs) : {type, value: ''}]
)
)
const restructure = (context) => ({
data: Object .fromEntries (context .groups .map (
({heading, inputs}) => [heading, convert (inputs)]
))
})
const context = {other: "props", groups: [{heading: "basic", canHaveMultiple: !1, inputs: [{name: "username", type: "text", placeholder: "username"}, {name: "password", type: "password", placeholder: "password"}]}, {heading: "about", canHaveMultiple: !1, inputs: [{name: "about", type: "textarea", placeholder: "about", canHaveMultiple: !1}]}, {heading: "hobbies", canHaveMultiple: !0, inputs: [{name: "title", type: "text", placeholder: "about", canHaveMultiple: !1}, {name: "description", type: "description", placeholder: null, canHaveMultiple: !1}]}, {heading: "friends", canHaveMultiple: !0, inputs: [{name: "name", type: "text", placeholder: "this is fine", canHaveMultiple: !1}, {name: "hobbies", type: "nested", canHaveMultiple: !0, inputs: [{name: "title", type: "textarea", placeholder: "about", canHaveMultiple: !1}, {name: "description", type: "textarea", placeholder: "about", canHaveMultiple: !1}]}]}]}
console .log (restructure (context))
.as-console-wrapper {max-height: 100% !important; top: 0}
第二個確實以一些額外的復雜性為代價添加了model/部分。value我不清楚它是否完全正確,盡管我認為它很接近:
const convert = (xs) => Object .fromEntries (
xs .map (({name, type, inputs = [], canHaveMultiple}) => [
name,
canHaveMultiple
? {model: convert (inputs), values: [convert (inputs)]}
: inputs.length ? convert (inputs) : {type, value: ''}
])
)
const restructure = (context) => ({
data: Object .fromEntries (context .groups .map (
({heading, inputs, canHaveMultiple}) => [
heading,
canHaveMultiple
? {model: convert (inputs), values: [convert (inputs)]}
: convert (inputs)
]
))
})
const context = {other: "props", groups: [{heading: "basic", canHaveMultiple: !1, inputs: [{name: "username", type: "text", placeholder: "username"}, {name: "password", type: "password", placeholder: "password"}]}, {heading: "about", canHaveMultiple: !1, inputs: [{name: "about", type: "textarea", placeholder: "about", canHaveMultiple: !1}]}, {heading: "hobbies", canHaveMultiple: !0, inputs: [{name: "title", type: "text", placeholder: "about", canHaveMultiple: !1}, {name: "description", type: "description", placeholder: null, canHaveMultiple: !1}]}, {heading: "friends", canHaveMultiple: !0, inputs: [{name: "name", type: "text", placeholder: "this is fine", canHaveMultiple: !1}, {name: "hobbies", type: "nested", canHaveMultiple: !0, inputs: [{name: "title", type: "textarea", placeholder: "about", canHaveMultiple: !1}, {name: "description", type: "textarea", placeholder: "about", canHaveMultiple: !1}]}]}]}
console .log (restructure (context))
.as-console-wrapper {max-height: 100% !important; top: 0}
如果你有一個一致的界面,我們可以簡化很多。也就是說,如果groupswas calledinputs和headingwas called name,我們可以將兩個重復的函式合并為一個。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/504519.html
標籤:javascript 目的 哎呀 递归 动态的
上一篇:VUE資料物件獲取屬性/值
