VueTreeselect 实现懒加载、多选、异步、回显。。。
是一个基于 Vue.js 的树形选择组件,专门用于在前端创建可交互的树形选择器。它具有树形结构、多选和单选、搜索和过滤、异步加载、自定义模板等特点和功能。项目上第一次使用VueTreeselect实现懒加载、多选、异步、回显等功能时,摸索了很久。以此记录,若有不足望纠正补充。安装:npm install --save @riophae/vue-treeselect。
·
VueTreeselect 是一个基于 Vue.js 的树形选择组件,专门用于在前端创建可交互的树形选择器。它具有树形结构、多选和单选、搜索和过滤、异步加载、自定义模板等特点和功能。
项目上第一次使用VueTreeselect实现懒加载、多选、异步、回显等功能时,摸索了很久。以此记录,若有不足望纠正补充。
安装:npm install --save @riophae/vue-treeselect
示例:
<template>
<Treeselect
ref="selectTree"
v-model="codeList"
:options="selectTreeData"
:multiple="true"
placeholder="请选择部门权限"
no-children-text="加载中..."
no-results-text="暂无数据"
no-options-text="暂无数据"
search-prompt-text="搜索中..."
:normalizer="normalizer"
:flat="true"
style="width: 100%;"
:load-options="loadOptions"
:async="isAsync"
@search-change="searchLoad"
@keydown.native="treeKeydown"
@keyup.native="treeKeyup($event)"
@open="itemopen"
@close="itemClose"
>
<!-- 需要回显时,因为是懒加载,树结构数据不完整,所以需要有回显项数据(包含label与id),再通过slot自定义展示label -->
<div slot="value-label" slot-scope="{ node }">
<span v-if="title === '回显'">
{{ node.raw.label?node.raw.label:getLabel(node.raw.id) }}
</span>
<span v-else>{{ node.raw.label }}</span>
</div>
</Treeselect>
</template>
关键点:
- multiple:默认false,定义true则打开多选;
- flat:默认false,定义true则让父节点和子节点在选中时不关联;
- no-children-text:默认是No sub-options(无子选项),因为是懒加载,children初始null,接口请求会有等待时间,显示“无子选项”再展示数据不友好。自定义为 "加载中...";
- async:动态判断是否异步搜索。懒加载及异步搜索会触发同一个方法@load-options,所以需要定义isAsync判断区分。如:@search-change即搜索时开启异步,@keydown、@keyup、@open、@close即输入时键的抬起,下拉框的打开和关闭时应该关闭异步;
- @load-option:动态加载数据,根据action区分是懒加载(LOAD_CHILDREN_OPTIONS)与异步搜索(ASYNC_SEARCH);
- 树结构数据初始加载前,节点children都需要置为 “null”,才会显示下拉图标触发@load-option。若能确定为叶子节点,则可置为 “[]”。
<script>
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
import { ASYNC_SEARCH } from '@riophae/vue-treeselect'
export default {
components: { Treeselect },
data() {
return {
codeList:[],
// 树结构默认数据
selectTreeData:[{
name:'a',
code:'01'
}],
// 异步回显,需要回显项的完整数据,否在树上没有找到时label会默认为id
defaultList:[{
name:'a',
code:'01'
},{
name:'aa',
code:'11'
}],
title:'回显',//如果需要回显时用,自定义节点label
isAsync:false//判断是异步搜索还是懒加载
},
},
mounted(){
},
methods:{
getDepartmentTreeData(parentId=0){
return new Promise(resolve => {
return []//返接口数据
})
},
// 格式化prop,当数据特殊时需要自定义,我这里就需要拿到code而不是id
normalizer(node) {
return {
id: node.code,
label: node.name,
children: node.children
}
},
// 过滤节点,不需要。
filterNode(value, data) {
// if (!value) return true
// return data.name.indexOf(value) > -1
},
// 异步搜索,当搜索值为空时展示初始树结构数据
searchLoad(query) {
if (!query) {
this.getDepartmentTreeData().then(res => {
this.selectTreeData = res//树结构数据
})
}
},
// 输入时打开异步,下拉open/close关闭异步
treeKeydown() {
this.isAsync = true
},
treeKeyup(e) {
if (!e.target.value) {
this.isAsync = false
}
},
itemopen(index) {
this.isAsync = false
},
itemClose(index) {
this.isAsync = false
},
// 动态加载数据:根据action区分是懒加载(LOAD_CHILDREN_OPTIONS)与异步搜索(ASYNC_SEARCH)
loadOptions({ action, parentNode, searchQuery, callback }) {
console.log(action, 'action')
if (action === LOAD_CHILDREN_OPTIONS) {
this.getDepartmentTreeData(parentNode.id).then(res => {
parentNode.children = res.length > 0 ? res : 0//空数组会展示“暂无数据”
})
callback()
} else if (action === ASYNC_SEARCH) {
const query = {
name: searchQuery,
pageSize: 100,
pageNum: 1
}
let arr = []
getOrgListByName(query).then(res => {//异步搜索方法
arr = res.arr
callback(null, arr)
})
}
},
//回显,根据id找label值,否则会默认id
getLabel(id) {
const obj = this.defaultList.find(item => {
return item.code=== id
})
return obj.name
},
}
</script>
更多推荐
已为社区贡献2条内容
所有评论(0)