我正在嘗試構建一個檔案夾樹組件,最初該組件只會呈現第一層的專案名稱(item1、item2、item3),然后當單擊特定專案時,它會顯示下一層列出的所有內容對于該專案(即單擊item1將顯示item1.1和item1.2,單擊item1.1將顯示item1.1.1)。這應該在一個回圈中完成,直到它到達只有屬性(attr1、attr2、attr3)的最后一層。
注意:出于演示目的,我已經簡化了專案名稱,但實際上它們并不遵循特定的模式/命名系統。
import React, {useState, useEffect} from 'react';
const Testing = () => {
const [expand, setExpand] = useState(false);
const data = {
"item1": {
"item1.1": {
"item1.1.1": {
"item1.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
},
"item1.2": {
"item1.2.1": {
"item1.2.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item2": {
"item2.1": {
"item2.1.1": {
"item2.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item2.1.2": {
"item2.1.2.1": {
"attr1": [],
"attr2": "",
"attr3": []
},
"item2.1.2.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item3": {
"item3.1": {
"item3.1.1": {
"item3.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item3.1.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
}
function parse(data) {
if (typeof data === 'object') {
return (
<li>
<ul>
{Object.entries(data).map(([key, value]) => (
<>
<li>
{key}: {typeof value === 'string' ? value : ''}
</li>
{parse(value)}
</>
))}
</ul>
</li>
);
}
if (typeof data === 'object') return (<li>{data}</li>);
return null;
}
return (
<div>
<div className="App">
{Object.entries(data).map(([key, value]) => {
return (
<ul>
<span onClick={() => setExpand(!expand)}>{key}</span>
<br />
<div style={{ display: expand ? "block" : "none", paddingLeft: 15 }}>
{parse(value)}
</div>
</ul>
);
})}
</div>
</div>
)
}
export default Testing;
這是我現在用上面的代碼得到的輸出圖片:current output ; 它在串列中顯示 item1、item2、item3;但是當我點擊它們中的任何一個時,它只會呈現其他所有內容,我正在嘗試找到一種方法,使其行為類似于檔案目錄樹,如下面的演示所示:https ://codesandbox.io/s /檔案夾結構-t6oj4
uj5u.com熱心網友回復:
問題在于,在演示中,他們使用了一個遞回組件,該組件具有自己的expand狀態,并通過鉤子進行管理。因此,對于在其范圍內Folder的變數,每個人都會有一個不同的值。expand
另一方面,您的Testing組件管理單個expand狀態,并且整個渲染為每個“檔案夾”使用該狀態,這就是為什么當您單擊檔案夾時它會切換整個組件的狀態,您應該做的是重構您的組件所以它還在每個檔案夾中管理自己的狀態,就像在演示中一樣:
import React, { useState } from "react";
function Folder ({ name, file }) {
const [expand, setExpand] = useState(false);
if (typeof file !== "object") return <span>{file}</span>;
return (
<div>
<span onClick={() => setExpand(!expand)}>{name}</span>
<br/>
<div style={{ display: expand ? "block" : "none", paddingLeft: 15 }} >
{
Object.entries(file).map(([key, value]) => (
<Folder key={key} name={key} file={value} />
))
}
</div>
</div>
);
}
然后在你的組件中呼叫它:
import React from 'react';
const Testing = () => {
const data = {
"item1": {
"item1.1": {
"item1.1.1": {
"item1.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
},
"item1.2": {
"item1.2.1": {
"item1.2.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item2": {
"item2.1": {
"item2.1.1": {
"item2.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item2.1.2": {
"item2.1.2.1": {
"attr1": [],
"attr2": "",
"attr3": []
},
"item2.1.2.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item3": {
"item3.1": {
"item3.1.1": {
"item3.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item3.1.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
}
return (
<div>
<div className="App">
<Folder name="/root" file={data} />
</div>
</div>
)
}
編輯:重構代碼,以便只有選定的檔案夾在單擊時展開
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/496379.html
標籤:javascript 反应 json 递归 array.prototype.map
上一篇:多針遞回搜索陣列-PHP
