100行代码实现VUE多级联动选框

我目前能想到的最简洁的代码实现的多级联动选框,理论上支持无限数量的的选框联动:

<template>
    <div class="c-selecter">
        <slot></slot>
        <Select v-for="(datas, i) in allData" :placeholder="placeholders[i] || '请选择'" :style="i>0?'margin-left: '+gap+'px;':''" v-model="model[i]" :key="i" @on-change="onSelectedChange(i)" :disabled="datas.length===0 && !placeholders[i]" >
            <Option v-for="item in datas" v-text="item[nameField]" :value="JSON.stringify(item)" selected v-bind:key="item[idField]">{{ item[nameField] }}</Option>
        </Select>
    </div>
</template>
<script>

export default {
  name: 'MultilevelSelecter',
  props: {
    /**
     * 显示级别数
     */
    levels: {
      type: Number,
      default: 3
    },
    /**
     * 数据加载器,必须是一个异步方法,返回的数据必须是对象数组
     */
    loader: {
      type: Function,
      default: () => {}
    },
    /**
     * 多个选框之间的间距
     */
    gap: {
      type: Number,
      default: 10
    },
    /**
     * 每个选择框的默认文字
     */
    placeholders: {
      type: Array,
      default: () => {
        return []
      }
    },
    idField: {
      type: String,
      default: 'id'
    },
    nameField: {
      type: String,
      default: 'name'
    }
  },
  data () {
    return {
      allData: [],
      model: []
    }
  },
  mounted () {
    this.dataMap = new Map()
    this.model = new Array(this.levels).fill(null)
    this.allData = new Array(this.levels).fill([])
    this.getLevelData(null)
  },
  methods: {
    async getLevelData (pid, level = 0) {
      if (level >= this.allData.length || pid === -1) {
        this.$emit('on-change', this.model.map(v => { return v ? JSON.parse(v) : null }))
        return
      }
      const cdata = this.dataMap.get(pid) || await this.loader(pid)
      this.allData[level] = cdata
      this.dataMap.set(pid, cdata)
      this.allData = [...this.allData]
      if (cdata.length) {
        this.model[level] = this.placeholders[level] ? null : JSON.stringify(cdata[0])
        this.getLevelData(cdata[0][this.idField], level + 1)
      } else {
        this.model[level] = null
        this.getLevelData(-1, level + 1)
      }
    },
    onSelectedChange (level) {
      this.getLevelData(this.model[level] ? JSON.parse(this.model[level])[this.idField] : -1, level + 1)
    }
  }
}
</script>
<style lang="less">
.c-selecter{
    display: inline-block;
    .ivu-select{
        width: auto;
        min-width: 100px;
    }
}
</style>

使用:

<MultilevelSelecter :placeholders="['省','市']" :id-field="'adcode'" :levels='2' :name-field="'name'" :loader="loader" @on-change="onCityChange">城市:</MultilevelSelecter>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值