ElTree Utils
2025-11-09 10:49:00
获取选中的树结构
getCheckedNodes.ts
test.ts
type TreeNode<T = any> = T & { children?: Array<TreeNode<T>> }
/**
* 根据选中 keys 过滤树结构,只保留选中节点及其父级
* @param tree 完整树结构
* @param checkedKeys 已选中的节点 key 列表
* @param keyField 节点唯一键名
*/
function getCheckedNodes<T>(
tree: Array<TreeNode<T>>,
checkedKeys: Array<string | number>,
keyField: keyof T
): Array<TreeNode<T>> {
const selectedSet = new Set(checkedKeys)
function filterNodes(nodes: TreeNode[]): TreeNode[] {
return nodes
.map(node => {
const children = node.children ? filterNodes(node.children) : []
const isSelected = selectedSet.has(node[keyField])
// 如果当前节点被选中或有选中的子节点,则保留
if (isSelected || children.length > 0) {
return { ...node, children }
}
return null
})
.filter(Boolean)
}
return filterNodes(tree)
}
获取当前选中的树节点key
getCheckedKeys.ts
test.ts
type TreeNode<T = any> = T & { children?: Array<TreeNode<T>> }
/**
* 根据完整树 fullTree 和部分树 targetTree 推算 checkedKeys(多层支持)
* @param fullTree 完整树
* @param targetTree 当前树(可能只包含部分节点,但需要和fullTree结构、嵌套关系相同)
* @param key 节点唯一键名
*/
export function getCheckedKeys<T>(
fullTree: Array<TreeNode<T>>,
targetTree: Array<TreeNode<T>>,
key: keyof T
): string[] {
const toKey = (n: T) => String(n[key])
// 记录 target 中显式出现的节点 key
const explicit = new Set<string>()
const explicitNoChildren = new Set<string>()
const dfsTarget = (n: TreeNode<T>) => {
const k = toKey(n)
explicit.add(k)
if (n.children?.length) n.children.forEach(dfsTarget)
else explicitNoChildren.add(k)
}
targetTree.forEach(dfsTarget)
const result = new Set<string>()
/** 返回当前节点是否被选中 */
const dfsFull = (n: TreeNode<T>): boolean => {
const k = toKey(n)
if (!n.children?.length) {
if (explicit.has(k)) result.add(k)
return explicit.has(k)
}
const allChildrenSelected = n.children.map(dfsFull).every(Boolean)
const parentExplicit = explicitNoChildren.has(k)
if (parentExplicit || allChildrenSelected) {
result.add(k)
n.children.forEach(c => result.add(toKey(c)))
return true
}
return false
}
fullTree.forEach(dfsFull)
return [...result]
}