本文译自: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