【vue+element UI】实现带全选、反选、联级、搜索的下拉多选框

halo小伙伴们,在开发的过程中是否有遇到需要为下拉多选框添加操作按钮的,如全选、反选、联级、搜索的下拉选框呢?如图所示:
在这里插入图片描述
这里我们需要借助vue-treeselect插件(官方地址)
第一步,安装vue-treeselect插件

npm install --save @riophae/vue-treeselect

第二步,封装下拉框组件

<template>
  <div class="store-tree-select store-tree-wrap">
  	// 以下的属性可以自己查阅vue-treeselect官方文档进行查看
    <xy-tree-select
        :placeholder="placeholder"
        value-consists-of="ALL_WITH_INDETERMINATE"
        noChildrenText="暂无数据"
        searchPromptText="请输入搜索关键字"
        noResultsText="无搜索结果"
        :normalizer="normalizer"
        :disable-branch-nodes="false"
        :auto-load-root-options="loading"
        :multiple="multiple"
        :limit="limit"
        :limitText="limitTextFun"
        :maxHeight="500"
        :disabled="disabled"
        :options="data"
        :value="currentValue"
        v-model="currentValue"
        :default-expand-level="defaultExpandLevel"
        :flat="flat"
        :auto-deselect-descendants="cascade"
        :auto-select-descendants="cascade"
        @open="treeSelectOpen"
        @close="treeSelectClose"
        @input="input">
      // 这里是顶部的控制按钮
      <div slot="before-list" v-if="multiple == true" style="padding:0 0 4px 6px;">
        <div class="before-list-item" @click="selAll">
          <i class="el-icon-finished"></i> 全选
        </div>
        <div class="before-list-item" @click="selBack">
          <i class="el-icon-refresh-left"></i> 反选
        </div>
        <div class="before-list-item" @click="doSelLink">
          <i class="el-icon-link"></i>&nbsp;<span ref="linkText">联级</span>
        </div>
      </div>
    </xy-tree-select>
  </div>
</template>

<script>
// 这里引入安装好的vue-treeselect插件
import TreeSelect from '@riophae/vue-treeselect'
// 这里记得要连样式一起引入哦
import '@riophae/vue-treeselect/dist/vue-treeselect.css'

export default {
  components: {
    xyTreeSelect: TreeSelect,
  },
  mounted() {
  	// 获取下拉框数据
    this.loadData();
  },
  props: {
    placeholder: {
      default: '请选择组织'
    },
    limit:{
      default:1
    },
    //是否多选
    multiple: {
      default: false
    },
    //是否禁用
    disabled: {
      default: false
    },
    //树类型:BLOC,BRAND,AREA
    type: {
      type: String,
      default: undefined,
    },
    //是否赖加载,默认true
    lazy: {
      type: Boolean,
      default: true,
    },
    //是否自动加载
    autoLoadData: {
      default: true
    },
    //初始值
    value: {
      default: null
    },
    // 加载时应自动扩展多少级分支节点。设置 Infinity 为默认使所有分支节点扩展
    defaultExpandLevel: {
      default: 2
    },
    flat:{
      default:true
    },
    //设置一开始的列表值   用于默认选中时候会提示‘无该门店权限’
    list:{
      default:Array,
    },
  },
  watch: {
    value(val) {
      this.currentValue = val;
    },
    list(val){
      if(val.length>=0){
        this.data = val
      }
    },
    // 监听点击的联级反联级切换文本内容,在computed中操作也是可以的
    openStatu(val){
      if(val){
        if(this.cascade){
          this.$nextTick(()=>{
            this.$refs.linkText.innerHTML = '联级'
          })
        }else {
          this.$nextTick(()=>{
            this.$refs.linkText.innerHTML = '反联级'
          })
        }
      }
    }
  },
  
  data() {
    return {
      loading: true,
      normalizer(node) {
        return {
          id: node.id,
          // 由于小编这里有显示判断,所以根据字段进行了部分文本渲染判断
          label: node.title==undefined?'无该门店权限' : node.title + (node.type == 1 ? '(品牌)' : node.type == 2 ? '(区域)' : '(门店)'),
          children: node.subs != null ? node.subs : undefined,
          isDisabled: node.disabled,
        }
      },
      itemDisabled_:false,
      data: [],
      currentValue: this.value,
      cascade: true, // false表示不级联  true表示级联

      allDataIds:[],
      selLink:true,
      openStatu:false,
    }
  },
  
  methods: {
  	// 联级按钮操作
    doSelLink(){
      this.$nextTick(() => {
        this.selLink = !this.selLink
        this.cascade = this.selLink
      })
      if(!this.cascade){
        this.$nextTick(()=>{
          this.$refs.linkText.innerHTML = '联级'
        })
      }else {
        this.$nextTick(()=>{
          this.$refs.linkText.innerHTML = '反联级'
        })
      }
    },
    // 反选
    selBack(){
      // console.log("已经选了的",this.currentValue)
      let hasSel = this.currentValue;     //已经选中的列表
      if(hasSel.length<=0){
        return;
      }
      let allList = this.allDataIds;      //全部的列表
      let readyList = [];                 //准备放新的
      readyList = hasSel.filter(x => allList.indexOf(x) == -1)
          .concat(allList.filter(x => hasSel.indexOf(x) == -1));
      this.currentValue = readyList
    },
    //全选
    selAll(){
      this.currentValue = this.allDataIds
    },
    
    funChildren(arr) {
      let childs = arr
      for (let i = childs.length; i--; i > 0) {
        if (childs[i].subs) {
          this.allDataIds.push(childs[i].id)
          this.funChildren(childs[i].subs)
        } else {
          this.allDataIds.push(childs[i].id)
        }
      }
      return this.allDataIds
    },
    clearInput() {
      this.currentValue = null;
    },
    input(value) {
      this.$emit('selectChange', value);
    },
    /**
     *当所选元素超过定义的限制时处理显示的消息的功能。
     */
    limitTextFun(count) {
      return '+' + count
    },
    loadData(){
      this.allDataIds = []
      this.data = this.$store.state.UserAreasTree.UserAreasTreeData;
      this.funChildren(this.data)
    },
    /**
     *菜单打开时,获取树结构的值, 这样可以每次都获取一下最新的
     */
    treeSelectOpen() {//UserAreasTree.js
      /*let data = this.$store.state.UserAreasTree.UserAreasTreeData;
      this.data = this.publicFun.deleteChildren(data, 'subs');*/
      this.allDataIds = []
      this.data = this.$store.state.UserAreasTree.UserAreasTreeData;
      this.funChildren(this.data)
      this.openStatu = true
    },
    treeSelectClose(){
      this.openStatu = false
    }
  },
}
</script>


<style>
.before-list-item{
  float:left;
  width: 33.33%;
  text-align: center;
  cursor: pointer
}

.before-list-item:hover{
  color: #2d8cf0;
}
.vue-treeselect__control .vue-treeselect__limit-tip {
  padding-top: 2px;
}

.vue-treeselect__control {
  height: 32px;
}

.vue-treeselect--has-value .vue-treeselect__multi-value {
  margin-bottom: 0;
}

.vue-treeselect__multi-value-item-container {
  padding-top: 2px;
}
.store-tree-wrap{
  line-height: 20px;
}


</style>

第三步,在需要该组件的页面引入该组件

// 使用组件
<xy-form-tree-select :value="filterForm.areaIds" :multiple="true" @selectChange="selectArea"/>
        
// 引入组件
import xyFormTreeSelect from "../../common/XyTreeSelectControl";

// 回调方法
selectArea(val) {
   this.filterForm.areaIds = val;
},

好啦,快去试试看可不可行吧,如果有更好的方法的小伙伴们记得跟小编分享一下你们的开发经验哦!文章来源地址https://uudwc.com/A/Eyn6o

原文地址:https://blog.csdn.net/XujiRe/article/details/129692860

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年07月24日 14:16
Windows任务栏卡死怎么办?电脑任务栏无响应的解决办法
下一篇 2023年07月24日 14:18