本文譯自:30-seconds-of-react。React 30 秒速學:全篇中文翻譯、學習,地址:30-seconds-of-react-zh_CN-umi,全部案例進行分析、註釋、上線。css
系列文章:react
實現一個可摺疊、無限層級、支持數組和對象的樹組件。git
toggled
屬性來肯定內容的初始狀態(摺疊/展開)。React.setState()
hook 來建立isToggled
狀態變量,並在最初爲它賦予傳入的 toggled
的值。<div>
來包裝組件的內容和用於改變組件的isToggled
狀態的<span>
元素。data
上的isParentToggled
,isToggled
,name
和Array.isArray()
肯定組件的外觀。data
中的每一個子節點,肯定它是對象仍是數組,並遞歸渲染子樹。<p>
元素。樣式:github
/* 樹節點的基本樣式 */
.tree-element {
margin: 0;
position: relative;
}
div.tree-element:before {
content: '';
position: absolute;
top: 24px;
left: 1px;
height: calc(100% - 48px);
border-left: 1px solid gray;
}
/* 切換顯示、隱藏的按鈕元素 */
.toggler {
position: absolute;
top: 10px;
left: 0px;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 5px solid gray;
cursor: pointer;
}
.toggler.closed {
transform: rotate(90deg);
}
/* 隱藏節點內容 */
.collapsed {
display: none;
}
複製代碼
樹組件,組件內容較多,在學習過程當中我也對其中的內容,分別進行了註釋:數組
import styles from "./TreeView.css";
function TreeView({ // 使用對象解構來設置某些傳入屬性的默認值 data, toggled = true, // 摺疊按鈕,是否處於摺疊狀態 name = null, // 當前屬性名,若是子元素是對象顯示 isLast = true, // 是否最後一個 isChildElement = false, // 是否子元素 isParentToggled = true // 是否被父節點摺疊 }) {
const [isToggled, setIsToggled] = React.useState(toggled);
return (
<div
style={{ marginLeft: isChildElement ? 16 : 4 + "px" }}
// 若是父摺疊就隱藏
className={isParentToggled ? styles["tree-element"] : styles.collapsed}
>
{/* 摺疊按鈕,點擊設置反狀態 */}
<span
className={
isToggled ? styles.toggler : `${styles.toggler} ${styles.closed}`
}
onClick={() => setIsToggled(!isToggled)}
/>
{name ? <strong> {name}: </strong> : <span> </span>}
{/* 開始符 */}
{Array.isArray(data) ? "[" : "{"}
{/* 子元素被摺疊 */}
{!isToggled && "..."}
{/* 渲染對象的子元素 */}
{Object.keys(data).map((v, i, a) =>
// 是對象,遞歸調用自身
typeof data[v] == "object" ? (
<TreeView
data={data[v]}
key={i}
isLast={i === a.length - 1}
// 子元素的屬性名,對象須要顯示屬性名,數組不顯示
name={Array.isArray(data) ? null : v}
isChildElement
isParentToggled={isParentToggled && isToggled}
/>
) : ( // 不是對象,顯示內容便可
<p
key={i}
style={{ marginLeft: 16 + "px" }}
className={isToggled ? styles["tree-element"] : styles.collapsed}
>
{Array.isArray(data) ? "" : <strong>{v}: </strong>}
{data[v]}
{i === a.length - 1 ? "" : ","}
</p>
)
)}
{/* 結束符 */}
{Array.isArray(data) ? "]" : "}"}
{/* 不是最後元素,加個逗號 */}
{!isLast ? "," : ""}
</div>
);
}
複製代碼
export default function() {
let data = {
lorem: {
ipsum: "dolor sit",
amet: {
consectetur: "adipiscing",
elit: [
"duis",
"vitae",
{
semper: "orci"
},
{
est: "sed ornare"
},
"etiam",
["laoreet", "tincidunt"],
["vestibulum", "ante"]
]
},
ipsum: "primis"
}
};
return <TreeView data={data} name="data" />; } 複製代碼
ps:post