故事背景: 接到一個(gè)自定義多級(jí)下拉的需求, 功能已經(jīng)完成,但是在提交數(shù)據(jù)時(shí)測(cè)試提出要做非空校驗(yàn), 意思就是如果有層級(jí)存在空字段, 需要跳到該層級(jí)并給出提示, 不用遞歸實(shí)現(xiàn)的話, 三次 for 循環(huán)還是挺好實(shí)現(xiàn)的, 但是作為一個(gè)有追求的 coder, 我們最終還是通過(guò)遞歸的方式來(lái)實(shí)現(xiàn)的,畢竟 leetcode 也刷了幾十道了, 也該考驗(yàn)一下刷題的效果了.
效果如下:
Kapture 2022-04-10 at 18.44.13.gif
首先我們來(lái)看下 json-tree 格式
/**
*@desc value 就是表單綁定的值
*/
[{
"value":"0",
"child":[{
"value":"0-0",
"child":[{
"value":"",
"nodeId":"c0",
"pnodeId":"b0",
"uniqueness":"0.14658520948272225"
}],
"nodeId":"b0",
"pnodeId":"a0",
"uniqueness":"0.49521203933283897"
}],
"nodeId":"a0",
"pnodeId":0,
"uniqueness":"0.6101862372680027"
},
{
"value":"1",
"child":[{
"value":"1-1",
"child":[],
"nodeId":"b0",
"pnodeId":"a1",
"uniqueness":"0.9895125407132053"
},
{
"value":"",
"child":[],
"nodeId":"b1",
"pnodeId":"a1",
"uniqueness":"0.25298626352369147"
}],
"nodeId":"a1",
"pnodeId":0
}]
寫(xiě)的有點(diǎn)糙,請(qǐng)不要介意,算法如下:
const indexs = [] // 用戶(hù)存儲(chǔ) index 路勁
let flag = true // 申明一個(gè)全局變量,可以在閉包中可以訪問(wèn), 從而使 for 可以跳出來(lái)
function formValidation(arr, l = 0) {
for (let i = 0; i < arr.length; i++) {
if (!flag) { // 跳出 for 循環(huán)的標(biāo)識(shí), 如果 value 為空, 深度向上遍歷跳出 for 循環(huán)
break
}
if (l === 0) { // 每一級(jí)的路徑我們是通過(guò) Array 形式 存儲(chǔ)的, 如果這里不清空, 校驗(yàn)下一列的時(shí)候還會(huì)存留上一列的數(shù)據(jù)
indexs.length = 0 // 這種方式清除 Array, 算是騷操作吧, 但確實(shí)優(yōu)化了判斷邏輯
}
indexs[l] = i // 將列的路徑存在 array 中
if (!String(arr[i].value).trim()) { // 判斷 value 是否為空, 為空就需要跳出 for 循環(huán), 這里用到了閉包, 代碼層面看只有一層, 但是實(shí)際運(yùn)行時(shí), 是 for 循環(huán)里面嵌套 for 循環(huán)的.
indexs.length = l // 將 數(shù)組的長(zhǎng)度 與 遞歸的深度保持一致(打個(gè)比方: 比如第一層第三級(jí)遍歷完了, 后面會(huì)繼續(xù)遍歷第二級(jí)數(shù)據(jù), 遍歷第二層數(shù)據(jù)時(shí), 之前的第三級(jí)數(shù)據(jù)我們是要清除的, 所以我們直接通過(guò) array length 來(lái)清除)
indexs[l] = i
flag = false
break
}
if (arr[i].child?.length) { // 有子集 遞歸遍歷
formValidation(arr[i].child, l + 1)
}
}
}