记录一下,使用 Ant Design Vue a-tree 需要实现可搜索且后台返回数据不是标准数据的问题
可搜索 自定义字段
实现自定义字段需要使用 Tree props
的 replaceFields 属性
<template>
<div>
<a-space>
<a-input v-model:value="basicData.searchValue" placeholder="请输入物料类别名称" />
</a-space>
<a-tree :tree-data="basicData.treeData" :replaceFields="basicData.replaceFields" :expandedKeys="basicData.expandedKeys" :auto-expand-parent="basicData.autoExpandParent" @expand="onExpand" @select="onSelect">
<!-- 查询到的字段样式变红 -->
<template #title="{ code }">
<span v-if="code.indexOf(basicData.searchValue) > -1">
{{ code.substr(0, code.indexOf(basicData.searchValue)) }}
<span style="color: #f50">{{ basicData.searchValue }}</span>
{{ code.substr(code.indexOf(basicData.searchValue) + basicData.searchValue.length) }}
</span>
<span v-else>{{ code }}</span>
</template>
</a-tree>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { TreeDataItem } from 'ant-design-vue/es/tree/Tree'
import { GetTree } from '/@/api/wms/basicDataModule/inventoryCategoryArchives'
/* 页面基础数据 */
const basicData = reactive({
searchValue: '',
expandedKeys: [] as string[],
backupsExpandedKeys: [] as string[],
autoExpandParent: false,
replaceFields: {
title: 'name',
key: 'code',
},
treeData: [] as TreeDataItem[],
})
/**
* @description: 获取树形数据
* @return {*}
* @author: WANAN
*/
const getTreeData = () => {
GetTree()
.then((res) => {
basicData.treeData = res
console.log(res)
})
.catch((err) => {
console.log(err)
})
}
getTreeData()
/* --------------------------- 树形 a-tree --------------------------- */
/**
* @description: 展开/收起节点时触发
* @param {*} keys
* @return {*}
* @author: WANAN
*/
const onExpand = (keys: string[]) => {
basicData.expandedKeys = keys
basicData.autoExpandParent = false
}
/**
* @description: 选中树形节点触发
* @param {*} selectedKeys
* @param {*} e
* @return {*}
* @author: WANAN
*/
const onSelect = (selectedKeys, _e) => {}
/**
* @description: 获取节点中含有value的所有key集合
* @param {*} value
* @param {*} tree
* @param {*} keyList
* @return {*}
* @author: WANAN
*/
const getkeyList = (value, tree, keyList) => {
//遍历所有同一级的树
for (let i = 0; i < tree.length; i++) {
let node = tree[i]
//如果该节点存在value值则push
if (node.code.indexOf(value) > -1) {
keyList.push(node.code)
}
//如果拥有孩子继续遍历
if (node.children) {
getkeyList(value, node.children, keyList)
}
}
//因为是引用类型,所有每次递归操作的都是同一个数组
return keyList
}
//该递归主要用于获取key的父亲节点的key值
const getParentKey = (key, tree) => {
let parentKey, temp
//遍历同级节点
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
if (node.children) {
//如果该节点的孩子中存在该key值,则该节点就是我们要找的父亲节点
//如果不存在,继续遍历其子节点
if (node.children.some((item) => item.code === key)) {
parentKey = node.code
} else if ((temp = getParentKey(key, node.children))) {
//parentKey = this.getParentKey(key,node.children)
//改进,避免二次遍历
parentKey = temp
}
}
}
return parentKey
}
//获取该节点的所有祖先节点
const getAllParentKey = (key, tree) => {
var parentKey
if (key) {
//获得父亲节点
parentKey = getParentKey(key, tree)
if (parentKey) {
//如果父亲节点存在,判断是否已经存在于展开列表里,不存在就进行push
if (!basicData.backupsExpandedKeys.some((item) => item === parentKey)) {
basicData.backupsExpandedKeys.push(parentKey)
}
//继续向上查找祖先节点
getAllParentKey(parentKey, tree)
}
}
}
watch(
() => basicData.searchValue,
(_newVal, _oldVal) => {
debugger
if (basicData.searchValue === '') {
basicData.expandedKeys = []
} else {
//首先将展开项与展开项副本置为空
basicData.expandedKeys = []
basicData.backupsExpandedKeys = []
//获取所有存在searchValue的节点
let candidateKeysList = getkeyList(basicData.searchValue, basicData.treeData, [])
//遍历满足条件的所有节点
candidateKeysList.map((item) => {
//获取每个节点的母亲节点
var key = getParentKey(item, basicData.treeData)
//当item是最高一级,父key为undefined,将不放入到数组中
//如果母亲已存在于数组中,也不放入到数组中
if (key && !basicData.backupsExpandedKeys.some((item) => item === key)) basicData.backupsExpandedKeys.push(key)
})
let length = basicData.backupsExpandedKeys.length
for (let i = 0; i < length; i++) {
getAllParentKey(basicData.backupsExpandedKeys[i], basicData.treeData)
}
basicData.expandedKeys = basicData.backupsExpandedKeys.slice()
basicData.autoExpandParent = true
}
},
{
immediate: false,
}
)
</script>
完整全部代码
<template>
<div>
<a-space>
<a-input v-model:value="basicData.searchValue" placeholder="请输入物料类别名称" />
</a-space>
<a-tree :tree-data="basicData.treeData" :replaceFields="basicData.replaceFields" :expandedKeys="basicData.expandedKeys" :auto-expand-parent="basicData.autoExpandParent" @expand="onExpand" @select="onSelect">
<!-- 查询到的字段样式变红 -->
<template #title="{ code }">
<span v-if="code.indexOf(basicData.searchValue) > -1">
{{ code.substr(0, code.indexOf(basicData.searchValue)) }}
<span style="color: #f50">{{ basicData.searchValue }}</span>
{{ code.substr(code.indexOf(basicData.searchValue) + basicData.searchValue.length) }}
</span>
<span v-else>{{ code }}</span>
</template>
</a-tree>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { TreeDataItem } from 'ant-design-vue/es/tree/Tree'
import { GetTree } from '/@/api/wms/basicDataModule/inventoryCategoryArchives'
/* 页面基础数据 */
const basicData = reactive({
searchValue: '',
expandedKeys: [] as string[],
backupsExpandedKeys: [] as string[],
autoExpandParent: false,
replaceFields: {
title: 'name',
key: 'code',
},
treeData: [] as TreeDataItem[],
})
/**
* @description: 获取树形数据
* @return {*}
* @author: WANAN
*/
const getTreeData = () => {
GetTree()
.then((res) => {
basicData.treeData = res
console.log(res)
})
.catch((err) => {
console.log(err)
})
}
getTreeData()
/* --------------------------- 树形 a-tree --------------------------- */
/**
* @description: 展开/收起节点时触发
* @param {*} keys
* @return {*}
* @author: WANAN
*/
const onExpand = (keys: string[]) => {
basicData.expandedKeys = keys
basicData.autoExpandParent = false
}
/**
* @description: 选中树形节点触发
* @param {*} selectedKeys
* @param {*} e
* @return {*}
* @author: WANAN
*/
const onSelect = (selectedKeys, _e) => {}
/**
* @description: 获取节点中含有value的所有key集合
* @param {*} value
* @param {*} tree
* @param {*} keyList
* @return {*}
* @author: WANAN
*/
const getkeyList = (value, tree, keyList) => {
//遍历所有同一级的树
for (let i = 0; i < tree.length; i++) {
let node = tree[i]
//如果该节点存在value值则push
if (node.code.indexOf(value) > -1) {
keyList.push(node.code)
}
//如果拥有孩子继续遍历
if (node.children) {
getkeyList(value, node.children, keyList)
}
}
//因为是引用类型,所有每次递归操作的都是同一个数组
return keyList
}
//该递归主要用于获取key的父亲节点的key值
const getParentKey = (key, tree) => {
let parentKey, temp
//遍历同级节点
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
if (node.children) {
//如果该节点的孩子中存在该key值,则该节点就是我们要找的父亲节点
//如果不存在,继续遍历其子节点
if (node.children.some((item) => item.code === key)) {
parentKey = node.code
} else if ((temp = getParentKey(key, node.children))) {
//parentKey = this.getParentKey(key,node.children)
//改进,避免二次遍历
parentKey = temp
}
}
}
return parentKey
}
//获取该节点的所有祖先节点
const getAllParentKey = (key, tree) => {
var parentKey
if (key) {
//获得父亲节点
parentKey = getParentKey(key, tree)
if (parentKey) {
//如果父亲节点存在,判断是否已经存在于展开列表里,不存在就进行push
if (!basicData.backupsExpandedKeys.some((item) => item === parentKey)) {
basicData.backupsExpandedKeys.push(parentKey)
}
//继续向上查找祖先节点
getAllParentKey(parentKey, tree)
}
}
}
watch(
() => basicData.searchValue,
(_newVal, _oldVal) => {
debugger
if (basicData.searchValue === '') {
basicData.expandedKeys = []
} else {
//首先将展开项与展开项副本置为空
basicData.expandedKeys = []
basicData.backupsExpandedKeys = []
//获取所有存在searchValue的节点
let candidateKeysList = getkeyList(basicData.searchValue, basicData.treeData, [])
//遍历满足条件的所有节点
candidateKeysList.map((item) => {
//获取每个节点的母亲节点
var key = getParentKey(item, basicData.treeData)
//当item是最高一级,父key为undefined,将不放入到数组中
//如果母亲已存在于数组中,也不放入到数组中
if (key && !basicData.backupsExpandedKeys.some((item) => item === key)) basicData.backupsExpandedKeys.push(key)
})
let length = basicData.backupsExpandedKeys.length
for (let i = 0; i < length; i++) {
getAllParentKey(basicData.backupsExpandedKeys[i], basicData.treeData)
}
basicData.expandedKeys = basicData.backupsExpandedKeys.slice()
basicData.autoExpandParent = true
}
},
{
immediate: false,
}
)
</script>