我正在使用实体记录来构建思维导图应用程序。 应用程序中的数据是一棵节点树,我希望能够通过撤消/重做来重新设置节点的父级。 我面临的问题是,即使撤消操作工作正常,但重做操作却不行。
我在一个简单的应用程序中重新创建了我的问题:
import { Component, For } from 'solid-js' import { createStore } from 'solid-js/store' import { createHistory } from 'solid-record' type Node = { id: number, children: Array<number> parentid: number } const initialValue = [ { id: 0, children: [1, 2, 3], parentid: -1 }, { id: 1, children: [], parentid: 0 }, { id: 2, children: [], parentid: 0 }, { id: 3, children: [], parentid: 0 }, ] const [state, setState] = createStore(initialValue) const undoHistory = createHistory() const changeState = () => { undoHistory.batch() const nodeid = 3 const oldparentid = 0 const newparentid = 2 let node = state[nodeid] let oldparent = state[oldparentid] let newparent = state[newparentid] // first remove node form parent's children undoHistory.add(setState, n => n.id === node.parentid, 'children', oldparent.children.filter(n => n !== node.id)) // then add to new parent's children undoHistory.add(setState, n => n.id === newparent.id, 'children', [...newparent.children, node.id]) // lastly, point to new parent undoHistory.add(setState, n => n.id === node.id, 'parentid', newparent.id) undoHistory.unbatch() } const App: Component = () => { return ( <> <For each={state}>{(node: Node) => <div>{`id: ${node.id}, parentid: ${node.parentid}, children: ${node.children}`}</div>}</For> <button onClick={changeState}>Change Parent of 3</button> <button onClick={() => undoHistory.undo()} disabled={!undoHistory.isUndoable()}>Undo</button> <button onClick={() => undoHistory.redo()} disabled={!undoHistory.isRedoable()}>Redo</button> </> ); }; export default App;
当单击“更改 3 的父级”按钮时,changeState 函数:
重做正确地将状态恢复到其初始值,其中 1,2,3 列为 0 的子级。
但是 Redo 将节点 0 的子节点列表设置为 3,而它应该将其设置为 1,2! 非常奇怪的是,如果我不设置节点 3 的 Parentis 属性,则不会发生这种情况,该属性与节点 0 的 Children 属性没有直接关系...
我怀疑这是一个引用与值类型的问题,或者可能是实体记录中的错误...... 有什么帮助吗?
P粉7295188062023-09-16 11:56:23
正如我所怀疑的,该问题是参考问题...... 执行第一个操作时,使用“搜索”函数 n => n.id === node.parentid 选择数组的正确元素。 但是,solid-record 存储命令历史的方式使得它只存储“节点”对象。 并且同一对象的parentid 属性被最后一个操作修改。 通过使用存储node.parentid的局部变量解决了该问题。
或者,在更好地阅读 SolidJS store API 文档之后,直接使用 id 而不是搜索功能,例如:
undoHistory.add(setState, node.parentid, 'children', oldparent.children.filter(n => n !== node.id))