vue2封装el-select,el-tree,支持筛选,实现TreeSelect的效果

1.项目要实现树状的选择,element-ui里面有el-cascader级联选择器可以实现,但是产品不想要级联选择器的实现效果,这个时候就利用element-ui的组件进行了二次封装

2.效果图(有样式要求可以自己调整)

3.element-ui的引入和安装就不赘述了,官网地址

4.封装利用了el-select,el-input,el-tree来实现

5.代码实现,外层el-select来绑定已经选中的数据并回显,内层el-input来做筛选,绑定一个数据,通过监听这个绑定的数据的变化来调用el-tree的筛选的方法,el-tree主要是用来处理数据的选中与取消

6.完整的代码(已经封装为组件了,可以直接复制使用)

<template>
  <div>
    <div v-if="readOnly">
      <el-tag v-for="(tag, index) in id" :key="index" class="mx-1" :closable="false" :disable-transitions="false">
        {{ tag.labelName }}
      </el-tag>
    </div>
    <div v-else>
      <el-select style="width: 100%;" v-model="labels" multiple placeholder="请选择" @remove-tag="handdleRemoveTag">
        <el-option :label="paramsQuery.label" :value="paramsQuery.id" style="height: auto" disabled>
          <div>
            <el-input placeholder="请输入筛选" v-model="filterValue" />
            <el-tree :data="queryData" show-checkbox default-expand-all node-key="labelId" ref="trees" highlight-current
              :check-strictly="true" @check="handdleChange" :filter-node-method="filterNode" :props="defaultProps" />
          </div>
        </el-option>
      </el-select>
    </div>
  </div>
</template>

<script>
import { queryBusiLevelLabelApi } from '@/api/businessinfoApi.js';
export default {
  props: {
    // 接收父组件传过来的默认数据,用于回显
    id: {
      type: Array,
      default() {
        return []
      }

    },
    // 接收父组件传过来的默认数据,用于回显
    label: {
      type: Array,
      default() {
        return []
      }
    },
    // 接收父组件传过来的el-tree的数据源
    data: {
      type: Array,
      default() {
        return [{
          id: 1,
          label: '一级 1',
          children: [{
            id: 4,
            label: '二级 1-1',
            children: [{
              id: 9,
              label: '三级 1-1-1'
            }, {
              id: 10,
              label: '三级 1-1-2'
            }]
          }]
        }, {
          id: 2,
          label: '一级 2',
          children: [{
            id: 5,
            label: '二级 2-1'
          }, {
            id: 6,
            label: '二级 2-2'
          }]
        }, {
          id: 3,
          label: '一级 3',
          children: [{
            id: 7,
            label: '二级 3-1'
          }, {
            id: 8,
            label: '二级 3-2'
          }]
        }]
      }

    },
    // el-tree的配置
    defaultProps: {
      type: Object,
      default() {
        return {
          children: 'childernLabel',
          label: 'labelName',
          id: 'labelId'
        }
      }

    },
    readOnly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // 接收父组件传来的id,label
      ids: [],
      labels: [],
      paramsQuery: {
        id: '',
        label: ''
      },
      // 筛选框绑定的字段
      filterValue: '',
      // 如何本页面发送请求,本页面发送请求的数据源
      queryData: []
    }
  },
  watch: {
    // 侦听filterValue 的变化,调用filter的方法
    filterValue(val) {
      this.$refs.trees.filter(val)
    },
    id: {
      handler(val) {
        console.log('val=======>', val);
        if (Array.isArray(val) && val.length) {
          let arrs = []
          this.ids = []
          this.labels = []
          val.forEach(it => {
            const foundObject = arrs.find(obj => obj.labelId === it.labelId && obj.labelName === it.labelName);
            if (!foundObject) {
              arrs.push(it)
              this.ids.push(it.labelId)
              this.labels.push(it.labelName)
            }
          })
          if (this.readOnly) {

          } else {
            this.$refs.trees.setCheckedNodes([])
            this.$refs.trees.setCheckedNodes(arrs)
          }
        }

      },
      deep: true
    },
  },
  mounted() {
    this.getData()
  },
  methods: {
    // el-tree选中发生改变触发,node为改变的数据,chenked为是否选中,选中为true,反之false
    handdleChange(checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys) {
      console.log('==================>', checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys)
      this.ids = checkedKeys.checkedKeys
      this.labels = []
      if (checkedKeys.checkedNodes.length) {
        checkedKeys.checkedNodes.forEach(item => {
          this.labels.push(item.labelName)
        })
      }
      const params = {
        id: this.ids,
        label: this.labels
      }
      //  数据改变将改变后的数据传给父组件处理
      this.$emit('changeLabelCallback', params)
    },
    // 筛选事件
    filterNode(value, data) {
      if (!value) return true
      return data.labelName.indexOf(value) !== -1
    },

    // 获取数据源
    getData() {
      queryBusiLevelLabelApi({ labelType: '业务标签' }).then((res) => {
        if (res.success) {
          this.queryData = res.object;
        }
      });
    },
    handdleRemoveTag(e) {
      console.log(e, this.labels);
      let code = ''
      this.queryData.forEach((i, idx) => {
        if (e == i.labelName) {
          code = i.labelId;
        } else {
          i.childernLabel.forEach((ii) => {
            if (e == ii.labelName) {
              code = ii.labelId;
            }
          });
        }
      });
      let leng = this.ids.indexOf(code)
      this.ids.splice(leng, 1);
      const arrs = []
      this.ids.forEach((it, index) => {
        arrs.push({
          labelId: it,
          labelName: this.labels[index]
        })
      })
      this.$refs.trees.setCheckedNodes(arrs)
    },
  }
}
</script>

<style lang="scss" scoped></style>

7.父组件引用

<tree-select2 :busilabel="formState.busiLevelLabelList"
                  :filterable="false"
                  :allowcreate="false"
                  @changeLabelCallback="changeLabel"></tree-select2>
``````引入
import treeSelect2 from '@/components/treeselect2.vue'
``````注册
 components: { treeSelect2 },
``````
// 需要回显的数据集合
id: [],
label: [],
``````
// 接收treeselect2返回的数据
    changeLabel(val) {
      console.log(val)
    }

 记录开发日常,如有不足还望指出,感谢!

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值