如何为带展开折叠的Tree View实现单元格行内编辑
分类树节点行内编辑实现方案
核心思路
每个节点需要两种状态:文本显示态和编辑态,通过状态管理切换;编辑完成后递归更新树结构数据,同时保留展开/折叠功能。
具体实现步骤(结合React代码)
1. 给TreeItem组件添加编辑状态
在TreeItem组件内部维护编辑状态和临时输入值,点击节点文本触发编辑:
import { useState } from "react"; const TreeItem = ({ item, level, toggleExpand, isExpanded, updateItem }) => { // 编辑状态:是否处于编辑模式 const [isEditing, setIsEditing] = useState(false); // 临时存储编辑内容,避免直接修改原始数据 const [editValue, setEditValue] = useState(item.name); // 保存编辑内容 const handleSave = () => { updateItem(item.id, editValue); setIsEditing(false); }; // 取消编辑,恢复原内容 const handleCancel = () => { setEditValue(item.name); setIsEditing(false); }; return ( <div style={{ paddingLeft: `${level * 20}px` }}> {/* 展开/折叠按钮,不受编辑状态影响 */} <button onClick={() => toggleExpand(item.id)}> {isExpanded ? "▼" : "▶"} </button> {/* 根据状态切换显示文本或输入框 */} {isEditing ? ( <> <input type="text" value={editValue} onChange={(e) => setEditValue(e.target.value)} // 失焦自动保存 onBlur={handleSave} // 回车保存、ESC取消 onKeyDown={(e) => { if (e.key === "Enter") handleSave(); if (e.key === "Escape") handleCancel(); }} // 进入编辑时自动聚焦 autoFocus /> <button onClick={handleSave}>保存</button> <button onClick={handleCancel}>取消</button> </> ) : ( // 点击文本进入编辑模式 <span onClick={() => setIsEditing(true)}>{item.name}</span> )} {/* 递归渲染子节点 */} {isExpanded && item.children && item.children.map((child) => ( <TreeItem key={child.id} item={child} level={level + 1} toggleExpand={toggleExpand} isExpanded={isExpanded} updateItem={updateItem} /> ))} </div> ); };
2. 父组件实现递归更新树数据
因为树是嵌套结构,需要递归找到目标节点并更新名称,在父组件中添加updateItem函数:
const [treeData, setTreeData] = useState(/* 你的原始树数据 */); // 递归更新节点名称 const updateItem = (targetId, newName) => { const updateRecursive = (nodes) => { return nodes.map(node => { if (node.id === targetId) { return {...node, name: newName}; } // 递归更新子节点 if (node.children) { return {...node, children: updateRecursive(node.children)}; } return node; }); }; setTreeData(updateRecursive(treeData)); };
3. 传递更新函数给子组件
在渲染根TreeItem时,把updateItem传递下去:
<TreeItem item={treeData} level={0} toggleExpand={/* 你的展开/折叠函数 */} isExpanded={true} updateItem={updateItem} />
优化建议
- 如果树节点数量较多,可以改用全局状态(比如
useReducer)记录当前编辑的节点ID,代替每个节点单独维护isEditing,提升性能 - 可以替换点击文本触发编辑的逻辑,改为添加单独的「编辑」图标按钮,避免误触
- 自定义输入框样式,让编辑态和显示态的排版保持一致
内容的提问来源于stack exchange,提问作者Luan Tran
相关产品推荐
相关产品推荐

