4 回答

TA貢獻1818條經驗 獲得超11個贊
感謝大家的回復真的幫助我到達那里,我最終得到了這個:
const setCSSVars = (obj: { [key: string]: any }, stack: string[] = []) => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === 'object' && value !== null) {
setCSSVars(value, [...stack, key])
} else {
document.documentElement.style.setProperty(
`--theme-${stack.join('-')}-${key}`,
value
)
}
})
}

TA貢獻1772條經驗 獲得超5個贊
您可以采用遞歸方法檢查對象并將嵌套的子結果映射到最終結果。
const
getPathes = object => Object
.entries(object)
.reduce((r, [k, v]) => {
if (v && typeof v === 'object') {
r.push(...getPathes(v).map(([p, v]) => [[k, ...p], v]));
} else {
r.push([[k], v]);
}
return r;
}, []),
theme = { fonts: { primary: 'Arial', secondary: 'Helvetica' }, colors: { primary: 'green', secondary: 'red' }, margin: { small: '0.5rem', medium: '1rem', large: '1.5rem' } };
console.log(getPathes(theme));
.as-console-wrapper { max-height: 100% !important; top: 0; }

TA貢獻2041條經驗 獲得超4個贊
另一種簡單的遞歸方法如下所示:
const pathEntries = (obj) =>
Object (obj) === obj
? Object .entries (obj) .flatMap (
([k, x]) => pathEntries (x) .map (([p, v]) => [[k, ... p], v])
)
: [[[], obj]]
const theme = {fonts: {primary: 'Arial', secondary: 'Helvetica'}, colors: {primary: 'green', secondary: 'red'}, margin: {small: '0.5rem', medium: '1rem', large: '1.5rem'}}
console.log(pathEntries(theme))
.as-console-wrapper {max-height: 100% !important; top: 0}
如果提供的值不是對象或數組,那么我們只返回像最終格式一樣包裝的對象,帶有一個空路徑:[[], obj]。如果它是一個對象或數組,我們平面映射對象的條目,重復它們的值,并將它們的鍵添加到遞歸調用中捕獲的每個結果路徑之前。
但我更愿意用更多可重復使用的部分來構建它。
const getPaths = (obj) =>
Object (obj) === obj
? Object .entries (obj) .flatMap (([k, v]) => getPaths (v) .map (p => [k, ... p]))
: [[]]
const path = (ps) => (obj) =>
ps .reduce ((o, p) => (o || {}) [p], obj)
const pathEntries = (obj) =>
getPaths (obj) .map (p => [p, path (p) (obj)])
const theme = {fonts: {primary: 'Arial', secondary: 'Helvetica'}, colors: {primary: 'green', secondary: 'red'}, margin: {small: '0.5rem', medium: '1rem', large: '1.5rem'}}
console .log (pathEntries (theme))
.as-console-wrapper {max-height: 100% !important; top: 0}
getPaths
找到你正在尋找的路徑(沒有值),產生類似[["fonts", "primary"], ["fonts", "secondary"], ..., ["margin", "large"]]
.path
采用該格式的路徑并返回一個函數,該函數采用一個對象,返回沿給定路徑在該對象中找到的值,或者undefined
是否缺少任何中間節(jié)點。pathEntries
是主要功能,它首先用于getPaths
查找對象中的所有葉路徑,然后通過使用將每個路徑映射到您的輸出格式path
。
在任何一種情況下,pathEntries
都特定于您有些不尋常的輸出格式。但是對于第二種方法,這兩個輔助函數在很多情況下都非常有用。
但是如果選擇第二種方法,您應該意識到它的性能不如第一種。它多次掃描對象,一次是為了找到路徑,并對每條路徑執(zhí)行部分遍歷。對于可重用部分,我仍然會選擇它而不是其他,除非分析告訴我它是我的代碼庫中的瓶頸。但是你應該記住這一點。

TA貢獻1804條經驗 獲得超3個贊
這是另一種方法。
您可以創(chuàng)建一個函數,該函數使用for of循環(huán)來迭代作為參數傳遞的對象的鍵。然后將當前鍵壓入一個臨時保存鍵的數組。之后,檢查當前鍵是否有一個不是對象的值。如果此條件為真,則將一個對象推入在函數外部創(chuàng)建的數組中,該數組將當前鍵的值作為鍵,并且其值應該是一個包含導致當前鍵值的所有鍵的數組。
如果當前鍵的值不是對象,則遞歸調用該函數并重復該過程。
PS:我使用了以下輸出格式。
[ { "Arial": [ "fonts", "primary" ] }, { "Helvetica": [ "fonts", "primary" ] } ]
const theme = {
fonts: { primary: 'Arial', secondary: 'Helvetica' },
colors: { primary: 'green', secondary: 'red' },
margin: { small: '0.5rem', medium: '1rem', large: '1.5rem' }
};
const keysArr = [];
function createKeyPath(obj, tempKeysArr = []) {
for (const k of Object.keys(obj)) {
// push current key in temporary array
tempKeysArr.push(k);
if (typeof obj[k] != 'object') {
// push a new object in keysArr
keysArr.push({ [obj[k]]: [...tempKeysArr] });
// remove last key from temporary key array
tempKeysArr.pop();
} else {
createKeyPath(obj[k], tempKeysArr);
// reset tempKeysArr
tempKeysArr = [];
}
}
}
createKeyPath(theme);
console.log(keysArr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
添加回答
舉報