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

halo小伙伴们,在开发的过程中是否有遇到需要为下拉多选框添加操作按钮的,如全选、反选、联级、搜索的下拉选框呢?如图所示:
【vue+element UI】实现带全选、反选、联级、搜索的下拉多选框_第1张图片
这里我们需要借助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;
},

好啦,快去试试看可不可行吧,如果有更好的方法的小伙伴们记得跟小编分享一下你们的开发经验哦!

你可能感兴趣的:(Element,UI,vue,elementui,vue)