问题
Antdv 中树形组件的select
事件的两个参数分别为selectedKeys
和e
,获取当前选中的节点的方法:
- 通过事件的
e.node.dataRef
获取 - 通过
selectedKey
获取
<a-tree
:tree-data="trees"
:replace-fields="{title: 'name', key: 'id'}"
:show-line="true"
@select="onSelect"
/>
第二种方案如果以记录的id
作key
就不得不对树结构进行展开或者递归。解决方案为:在组装树的时候生成路径来作为key
。
解决
路径ID数组转JSON工具方法(需配置Jackson将Long
序列化String
):
private String pathIdsToJsonArray(List<Long> pathIds) {
String pathIdJsonArray;
try {
pathIdJsonArray = objectMapper.writeValueAsString(pathIds);
} catch (JsonProcessingException e) {
pathIdJsonArray = "";
}
return pathIdJsonArray;
}
组装成树:
public List<Category> getCategoryTreeList() {
List<Category> nodes = super.list();
return nodes.stream()
.filter(node -> node.getParentId() == 0)
.peek(node -> {
List<Long> pathIds = new ArrayList<>();
// 一级分类只添加自身ID
pathIds.add(node.getId());
String pathIdJsonArray = this.pathIdsToJsonArray(pathIds);
node.setPathIdJsonArray(pathIdJsonArray);
this.combineToTree(node, pathIds, nodes);
})
.collect(Collectors.toList());
}
private void combineToTree(Category root, List<Long> rootPathIds, List<Category> nodes) {
List<Category> children = nodes.stream()
.filter(node -> node.getParentId().equals(root.getId()))
.peek(node -> {
// 非一级分类先添加父分类的路径数组再添加自身ID
List<Long> pathIds = new ArrayList<>(rootPathIds);
pathIds.add(node.getId());
String pathIdJsonArray = this.pathIdsToJsonArray(pathIds);
node.setPathIdJsonArray(pathIdJsonArray);
this.combineToTree(node, pathIds, nodes);
})
.collect(Collectors.toList());
root.setChildren(children);
}
组件(单选):
<template>
<a-tree
:tree-data="trees"
:replace-fields="{title: 'name', key: 'pathIdJsonArray'}"
:show-line="true"
@select="onSelect"
/>
</template>
<script>
export default {
props: {
trees: { type: Array, default: () => [] }
},
methods: {
onSelect ([pathIdJsonArray1]) {
// [一级分类ID, 二级分类ID, ...剩余分类ID]
const pathIds = JSON.parse(pathIdJsonArray1)
let target = { children: this.trees }
for (let i = 0; i < pathIds.length; i++) {
target = target.children.find(item => item.id === pathIds[i])
}
this.$emit('selectedNode', target)
}
}
}
</script>