前言
工作中会遇到展示机构信息或者目录等树状结构的数据的情况,elementUI中的el-select和el-tree树形控件搭配实现就显得有些麻烦复杂,所以一般通过个性化Ant Design Vue中的treeselect组件来实现想要的效果。如果数据量少可以直接使用组件不做任何更改,如果数据量过大会导致页面渲染加载速度过慢。比如某银行的分行,部门机构信息一共有三千六百多条,所以只能懒加载数据。另外滑动到顶部再下划会刷新数据,滑动到底部再上划会加载更多数据,以及模糊搜索功能。
正文代码
第一步,创建公共子组件BranchTreeSelect.vue
<template v-slot>
<a-tree-select
v-model="currentBranchNumber"
tree-data-simple-mode
style="width:100%"
:dropdown-style="{maxHeight: '400px', overflow: 'auto'}"
:tree-data="branchTreeData"
allow-clear
:show-search="true"
:load-data="onLoadTreeData"
:search-value="searchValue"
placeholder="请选择机构或分行"
@search="onSearch"
@clear="clearSelect"
@focus="focusSelect"
/>
</template>
<script>
import { getCurrentBranchAndChildrenBranchInfos, getCurrentBranchInfo } from '@/api/user'
export default {
name: 'BranchTreeSelect',
props: {
branchNumber: {
type: String
}
},
data() {
return {
branchTreeData: [],
searchValue: '',
currentBranchNumber: '',
allowSearchFlag: true
}
},
watch: {
'currentBranchNumber': {
handler(val) {
if (val) {
this.$emit('setBranchNumber', this.currentBranchNumber.toString().split(':')[0])
} else {
this.$emit('setBranchNumber', '')
}
}
}
},
created() {
this.initValue(this.branchNumber) // 初始化机构树
},
methods: {
initValue(val) {
this.currentBranchNumber = val
},
onSearch(val) { // 可以模糊检索, 需要后端支持
// 是否允许进行检索, 上一次检索数据还没渲染好不允许检索
if (this.allowSearchFlag && !isNaN(parseInt(val)) && isFinite(val) && val.length > 2) { // 机构号至少3位数字时才可以检索
this.allowSearchFlag = false
getCurrentBranchInfo(val).then(res => {
this.branchTreeData = []
const treeArray = []
res.forEach(function(item) {
const node = {
id: item.branchNumber,
pId: item.upperBranch,
value: (item.branchNumber + ':' + item.branchName),
title: (item.branchNumber + ':' + item.branchName),
isLeaf: item.isLeafBranch !== 'N'
}
treeArray.push(node)
})
this.branchTreeData = this.branchTreeData.concat(treeArray) // 拼接数组数据
this.allowSearchFlag = true
})
}
},
focusSelect() { // 聚焦的时候查询数据, 机构id传空查询根机构以及根机构下直接子机构。如果branchTreeData有数据, 则不再查询后端数据。如果生成树结构数据过程中也不会查询后端数据。
if (this.branchTreeData.join() === '' && this.allowSearchFlag) {
getCurrentBranchAndChildrenBranchInfos('').then(res => {
this.setTreeNode('', res)
})
}
},
clearSelect() { // 清空选中的机构, 则重新向后端查询根机构以及根机构下直接子机构
this.branchTreeData = []
getCurrentBranchAndChildrenBranchInfos('').then(res => {
this.setTreeNode('', res)
})
},
setTreeNode(parentId, dataList) { // 根据后端返回的结果生成树结构
this.allowSearchFlag = false // 生成树结构的过程中不允许检索, 因为会导致数据的错漏...期待后续优化
const treeArray = []
dataList.forEach(function(item) {
const node = {
id: item.branchNumber,
pId: parentId,
value: (item.branchNumber + ':' + item.branchName),
title: (item.branchNumber + ':' + item.branchName),
isLeaf: item.isLeafBranch !== 'N'
}
treeArray.push(node)
})
const tempArr = this.branchTreeData.concat(treeArray)
const newArr = []
for (const i in tempArr) {
if (!newArr.some(res => res.id === tempArr[i].id)) {
newArr.push(tempArr[i])
}
}
this.branchTreeData = newArr
this.allowSearchFlag = true
},
onLoadTreeData(treeNode) { // 加载更多数据
return new Promise(resolve => {
const { id } = treeNode.dataRef
setTimeout(() => {
getCurrentBranchAndChildrenBranchInfos(id).then(res => {
this.setTreeNode(id, res)
resolve()
})
}, 300)
})
}
}
}
</script>
<style scoped>
</style>
第二步,在父组件中调用公共子组件
<branch-tree-select :branch-number="formData.branchNumber" @setBranchNumber="setBranchNumber" />
export default {
import BranchTreeSelect from '@/components/BranchTreeSelect'
components: {
BranchTreeSelect
},
methods: {
setBranchNumber(val) {
// val是子组件选中值后传过来的机构号
}
}
}
如有问题请在下方留言,我会认真的查看每一条并尽量的给予回复。谢谢观看^^