VueTreeselect 实现懒加载、多选、异步、回显。。。

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>
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值