[英]Vue - Storing a tree in Pinia
我要问的问题是关于 Pinia 的,但实际上可以推广到任何基础商店。
我有一个 Vue + Pinia 应用程序,我希望能够在其中存储一棵树。 该树由Node
类型的对象组成。 我需要一次只存储一棵树,我不关心根(我们可以想象它在那里,但我关心的是根的孩子,他们的孩子,等等)。
我想支持以下操作:
这是我想做的事情:
Node
数组。 我们称它为topLevelNodes
nodeIdToChildren
,它将节点的 id 映射到作为其子节点的Node
数组我最初会获取顶级节点,填充数组topLevelNodes
。
对于每个需要知道其子节点的节点,获取它们并将它们作为键放入父 ID 下的nodeIdToChildren
中。
这种方法的一个优点是很容易添加、删除和移动节点:只需触摸映射中的相关条目。 最大的缺点是只找到一个节点的效率要低得多,不管它的 position。假设我想编辑 id 为xyz
的节点,不知道它是谁的孩子。
我可以创建一个吸气剂,将映射 object 中的所有值与顶级节点数组中的值一起展平,但我不确定其效率。
有没有更好的方法来做到这一点?
最有效的方法是将所有节点存储在一个数组中,而在一个节点的子/父数组中,您只放置其他节点的 ID。
parents
,但它返回所有项目的 ids,这些项目当前在他们的 children 数组中包含当前项目的 id。 同样,如果您存储父母,则孩子将被计算。注意事项:
getItemDetails
))children
ID 数组中删除它的 ID,将它的 ID 添加到新父母的children
中。孩子本身不受影响,除了值它的parents
计算的变化。如果你正在存储parents
, - 并且计算了children
- 你需要改变孩子的parents
数组。当然,当你执行这个改变时,每个新旧父母的children
计算都会改变) . 您可以在此处查看工作演示。 对不起 styles,我只是从不同的沙盒中调整了一些东西。 但是你得到了<TreeView />
和<TableView />
的基本实现。 这个有 1k 个节点,但最多 5k 个节点应该没有问题。 除此之外,您需要注意渲染的内容和时间。
这不是Vue/Pinia特有的,所以我只是写了大概的思路,你可以选择实现的方式。
您将把您的树存放在一个平面 map 上。
const tree = new Map()
每个项目都是一个node
,键是nodeId
。 每个节点将包含以下属性:
{
id: "the node id",
parentId: "id of the parent, null if it is the root node",
childIds: "array of the id of its child",
content: "content of the node, whatever you want"
}
让我们通过您想要的每个运营商 go:
// difficulty: easy
const rootNode = {
id: "nodeId"
parentId: null,
childIds: [...],
content: "..."
}
tree.set(nodeId, rootNode)
// difficulty: easy
// add the child first
const childNode = {
id: "nodeId"
parentId: "parentId",
childIds: [...],
content: "..."
}
tree.set(nodeId, childNode)
// add the child id to the parent node
const parentNode = tree.get(parentId)
parentNode.childIds.push(childNode.id)
// set the parent back to your tree
tree.set(parentNode.id, parentNode)
// modify a node.
// difficulty: easy
const node = tree.get(nodeId)
// ... make the modification
// set it back to the tree
tree.set(nodeId, node)
// delete a node.
// difficulty: medium
// retrieve the node first
const node = tree.get(nodeId)
// delete it
tree.delete(nodeId)
// delete all of its children
// you need a recursive delete function here to go through all of the node child and child of child and so on
tree.childIds.forEach(recursiveDelete)
// don't forget to delete the nodeId from its parent node. It's easy
...
// moving around the tree is quite easy, you just need to follow the `parentId` and `childIds`
// changing a node's parent (same level)
// difficulty: easy
// you just need to change the parentId of the node. And modify the childIds of its old and new parent
// changing a node level, moving its children accordingly
// difficulty: easy
// same as changing a node parent above. Its children will move accordingly
// changing a node level to be a child of one of its children
// difficulty: hard
// get the node
const node = tree.get(nodeId)
// go through its children and update the parentId of each to the node.parentId (moving its children to be the direct child of its parent)
node.childIds.forEach((childId)=> updateParentId(childId, node.parentId))
// set the node parentId to the new one
node.parentId = newParentId
// set new childIds for the node if you want
node.childIds = [...]
// don't forget to set it back on the tree
tree.set(node.id, node)
// There is no problem at all. You just need to load from the root
优点和缺点
优点:
缺点
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.