您好,登錄后才能下訂單哦!
這篇文章主要介紹“react如何給樹增加節點”,在日常操作中,相信很多人在react如何給樹增加節點問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”react如何給樹增加節點”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
react給樹增加節點的方法:1、引入antd的樹形控件,并通過“const treeData = [...]”實現tree形組件;2、把當前節點的key值傳遞過去,然后遍歷data數組;3、在遍歷數組增加節點時,通過嵌套數組對象的查詢算法實現增加節點即可。
React項目引入antd的樹形控件實現節點增刪改
使用過antd的小伙伴應該都知道,使用antd就是把它的代碼示例粘貼下來,然后根據自己的需求和antd提供的API進行更改。所以這里我也是找一個簡單antd樹形控件代碼示例,不管三七二十一先粘貼進去看看結果怎么樣。
import React from "react";
import { Tree } from "antd";const treeData = [
{
title: "0-0",
key: "0-0",
children: [
{
title: "0-0-0",
key: "0-0-0",
children: [
{ title: "0-0-0-0", key: "0-0-0-0" },
{ title: "0-0-0-1", key: "0-0-0-1" },
{ title: "0-0-0-2", key: "0-0-0-2" },
],
},
{
title: "0-0-1",
key: "0-0-1",
children: [
{ title: "0-0-1-0", key: "0-0-1-0" },
{ title: "0-0-1-1", key: "0-0-1-1" },
{ title: "0-0-1-2", key: "0-0-1-2" },
],
},
{
title: "0-0-2",
key: "0-0-2",
},
],
},
{
title: "0-1",
key: "0-1",
children: [
{ title: "0-1-0-0", key: "0-1-0-0" },
{ title: "0-1-0-1", key: "0-1-0-1" },
{ title: "0-1-0-2", key: "0-1-0-2" },
],
},
{
title: "0-2",
key: "0-2",
},];export default function TreeDemo() {
return (
<div>
<Tree treeData={treeData} />
</div>
);}
這里就實現了一個簡單的tree形組件,但是這個組件除了可以瀏覽之外,基本沒什么作用,所以還需要對它進行再度改造。
一般使用antd組件的時候,最重要的就是使用antd提供的API,咱們雖然不會寫,但是會用應該還是挺容易的。在瀏覽樹形控件的API時發現,<Tree/>
組件有個子組件<TreeNode/>
,它就是組成整個樹形控件的最小單元。所以我們如果要實現增刪改的話,就要在這個<TreeNode/>
組件上下功夫。根據這個思路然后改造成如下的樣子。
import React, { useState } from "react";import { Tree } from "antd";const { TreeNode } = Tree;const treeData = [
{
value: "0",
key: "0",
children: [
{
value: "0-1",
key: "0-1",
},
{
value: "0-2",
key: "0-2",
},
],
},];export default function TreeDemo() {
const [data, setdata] = useState(treeData);
const renderTreeNodes = (data) => {
let nodeArr = data.map((item) => {
item.title = <span>{item.value}</span>;
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.title} key={item.key} />;
});
return nodeArr;
};
return (
<div>
<Tree>{renderTreeNodes(data)}</Tree>
</div>
);}
然后就是如下的樣子:
這里要說明的一點是<TreeNode/>
的title接收的是ReactNode類型數據,所以大家可以根據這個來自己定義要展示數據的樣式,比如加上icon之類的。然后到這里,大家應該就知道了,需求里面不是說要有增刪改的功能嗎,正好可以借助這個title來展示一下,勝利就在眼前,接著改造代碼。
import React, { useState } from "react";import { Tree } from "antd";import {
EditOutlined,
PlusOutlined,
MinusOutlined,
} from "@ant-design/icons";const { TreeNode } = Tree;const treeData = [
{
value: "0",
key: "0",
children: [
{
value: "0-1",
key: "0-1",
},
{
value: "0-2",
key: "0-2",
},
],
},];export default function TreeDemo() {
const [data, setdata] = useState(treeData);
const renderTreeNodes = (data) => {
let nodeArr = data.map((item) => {
item.title = (
<div>
<span>{item.value}</span>
<span>
<EditOutlined style={{ marginLeft: 10 }} />
<PlusOutlined style={{ marginLeft: 10 }} />
<MinusOutlined style={{ marginLeft: 10 }} />
</span>
</div>
);
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.title} key={item.key} />;
});
return nodeArr;
};
return (
<div>
<Tree>{renderTreeNodes(data)}</Tree>
</div>
);}
現在就有了三個按鈕了,具體功能還是沒有的,那就一個一個來唄。
增加節點,實現方法就是把當前節點的key值傳遞過去然后遍歷data數組,在遍歷數組增加節點的時候,涉及到嵌套數組對象的查詢算法,這就用到了前兩周學習的數組的深度優先和廣度優先遍歷思想。
下面是根據這個思路修改的代碼:
import React, { useState } from "react";import { Tree } from "antd";import { EditOutlined, PlusOutlined, MinusOutlined } from "@ant-design/icons";const { TreeNode } = Tree;const treeData = [
{
value: "0",
key: "0",
children: [
{
value: "0-1",
key: "0-1",
},
{
value: "0-2",
key: "0-2",
},
],
},];export default function TreeDemo() {
const [data, setdata] = useState(treeData);
const renderTreeNodes = (data) => {
let nodeArr = data.map((item) => {
item.title = (
<div>
<span>{item.value}</span>
<span>
<EditOutlined style={{ marginLeft: 10 }} />
<PlusOutlined style={{ marginLeft: 10 }} onClick={()=>onAdd(item.key)} />
<MinusOutlined style={{ marginLeft: 10 }} />
</span>
</div>
);
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.title} key={item.key} />;
});
return nodeArr;
};
const onAdd = (key) => {
addNode(key,treeData);
//useState里數據務必為immutable (不可賦值的對象),所以必須加上slice()返回一個新的數組對象
setdata(treeData.slice())
};
const addNode = (key,data) =>
data.forEach((item) => {
if (item.key === key) {
if (item.children) {
item.children.push({
value: "default",
key: key + Math.random(100), // 這個 key 應該是唯一的
});
} else {
item.children = [];
item.children.push({
value: "default",
key: key + Math.random(100),
});
}
return;
}
if (item.children) {
addNode(key, item.children);
}
});
return (
<div>
<Tree>{renderTreeNodes(data)}</Tree>
</div>
);}
點擊添加按鈕出現一個新的default節點:
有了上面增加的節點的思想以后,后面的編輯和刪除功能就比較好做了。這里只展示代碼片段,文章最后有最終版本的代碼。在編輯節點的時候要把該節點變成可編輯的狀態,所以有就需要用一個變量來管理它。
const onEdit = (key) => {
editNode(key, treeData);
setData(treeData.slice())
};
const editNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
item.isEditable = true;
} else {
item.isEditable = false;
}
item.value = item.defaultValue; // 當某節點處于編輯狀態,并改變數據,點擊編輯其他節點時,此節點變成不可編輯狀態,value 需要回退到 defaultvalue
if (item.children) {
editNode(key, item.children);
}
});const treeData = [
{
value: "0",
key: "0",
isEditable: false,
children: [
{
value: "0-1",
key: "0-1",
isEditable: false,
},
{
value: "0-2",
key: "0-2",
isEditable: false,
},
],
},];
const onDelete = (key) => {
deleteNode(key, treeData);
setData(treeData.slice());
};
const deleteNode = (key, data) =>
data.forEach((item, index) => {
if (item.key === key) {
data.splice(index, 1);
return;
} else {
if (item.children) {
deleteNode(key, item.children);
}
}
});
五、完整代碼
import React, { useState} from "react";import { Tree } from "antd";import {
EditOutlined,
PlusOutlined,
MinusOutlined,
CloseOutlined,
CheckOutlined,} from "@ant-design/icons";import {nanoid} from "nanoid";const { TreeNode } = Tree;const treeData = [
{
value: "0",
defaultValue: "0",
key: "0",
parentKey: '0',
isEditable: false,
children: [
{
value: "0-1",
key: "0-1",
defaultValue: "0-1",
isEditable: false,
},
{
value: "0-2",
key: "0-2",
defaultValue: "0-2",
isEditable: false,
},
],
},];const expandedKeyArr = ["0"];export default function TreeDemo() {
const [data, setData] = useState(treeData);
const [expandedKeys, setExpandedKeys] = useState(expandedKeyArr);
const onExpand = (expandedKeys) => {
//記錄折疊的key值
setExpandedKeys(expandedKeys);
};
const renderTreeNodes = (data) => {
let nodeArr = data.map((item) => {
if (item.isEditable) {
item.title = (
<div>
<input value={item.value ||''} onChange={(e) => onChange(e, item.key)} />
<CloseOutlined
style={{ marginLeft: 10 }}
onClick={() => onClose(item.key, item.defaultValue)}
/>
<CheckOutlined
style={{ marginLeft: 10 }}
onClick={() => onSave(item.key)}
/>
</div>
);
} else {
item.title = (
<div>
<span>{item.value}</span>
<span>
<EditOutlined
style={{ marginLeft: 10 }}
onClick={() => onEdit(item.key)}
/>
<PlusOutlined
style={{ marginLeft: 10 }}
onClick={() => onAdd(item.key)}
/>
{item.parentKey === "0" ? null : (
<MinusOutlined
style={{ marginLeft: 10 }}
onClick={() => onDelete(item.key)}
/>
)}
</span>
</div>
);
}
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.title} key={item.key} />;
});
return nodeArr;
};
const onAdd = (key) => {
if (expandedKeys.indexOf(key) === -1) {
expandedKeyArr.push(key);
}
setExpandedKeys(expandedKeyArr.slice());
addNode(key, treeData);
//useState里數據務必為immutable (不可賦值的對象),所以必須加上slice()返回一個新的數組對象
setData(treeData.slice());
};
const onEdit = (key) => {
editNode(key, treeData);
setData(treeData.slice());
};
const editNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
item.isEditable = true;
} else {
item.isEditable = false;
}
item.value = item.defaultValue; // 當某節點處于編輯狀態,并改變數據,點擊編輯其他節點時,此節點變成不可編輯狀態,value 需要回退到 defaultvalue
if (item.children) {
editNode(key, item.children);
}
});
const addNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
if (item.children) {
item.children.push({
value: "default",
key: nanoid(), // 這個 key 應該是唯一的
});
} else {
item.children = [];
item.children.push({
value: "default",
key: nanoid(),
});
}
return;
}
if (item.children) {
addNode(key, item.children);
}
});
const onChange = (e, key) => {
changeNode(key, e.target.value, treeData);
setData(treeData.slice());
};
const changeNode = (key, value, data) =>
data.forEach((item) => {
if (item.key === key) {
item.value = value;
}
if (item.children) {
changeNode(key, value, item.children);
}
});
const onSave = (key) => {
saveNode(key, treeData);
setData(treeData.slice());
};
const saveNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
item.defaultValue = item.value;
}
if (item.children) {
saveNode(key, item.children);
}
item.isEditable = false;
});
const onClose = (key, defaultValue) => {
closeNode(key, defaultValue, treeData);
setData(treeData);
};
const closeNode = (key, defaultValue, data) =>
data.forEach((item) => {
item.isEditable = false;
if (item.key === key) {
item.value = defaultValue;
}
if (item.children) {
closeNode(key, defaultValue, item.children);
}
});
const onDelete = (key) => {
deleteNode(key, treeData);
setData(treeData.slice());
};
const deleteNode = (key, data) =>
data.forEach((item, index) => {
if (item.key === key) {
data.splice(index, 1);
return;
} else {
if (item.children) {
deleteNode(key, item.children);
}
}
});
return (
<div>
<Tree expandedKeys={expandedKeys} onExpand={onExpand}>
{renderTreeNodes(data)}
</Tree>
</div>
);}
到此,關于“react如何給樹增加節點”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。