el-cascader级联组件动态加载数据允许选择任意一级的选项或只能选择最后一级

el已于2.9.2版本更新懒加载方法 详细请前往官网查看

2020年1月10日 更新

突然看到这个代码 就继续研究了一下 添加了懒加载时可以只选最后一级 就是没有children的那一级
首先el-cascader中change-on-select是控制是否允许选择任意层级的

当值为true时 每次点击item都会触发change事件 但不会触发active-item-change事件

当值为false时 每次点击item都会触发active-item-change事件 但不会触发change事件

于是…当组件化时不确定change-on-select到底传啥时,我就同时监听这俩事件

具体的话 可以看下面的代码 注释也更新了


问题描述

这个功能主要的难点在于多级时,动态加载出的数据该塞到哪个节点下,下面的内容主要就是解决这个问题的。

el-cascader级联组件动态加载数据

首先理一下思路,假设点击第一层某个选择,通过change事件获取值,并请求,返回的数据放到第一层哪一条?
再看一下elementUI官网对于prop中的value介绍
在这里插入图片描述

也就是说通过change获取到的value是string类型,如果获取到的是个对象,那么就可以把当前数据的索引放在当前数据的某个键里,再通过索引将后台返回的数据放入选项里.

总结下来,就剩一个问题了,就是如何获取一整条对象,而不是一个字符串,只需要把当前数据通过JSON.stringify()转换成字符串,选中时,再将字符串转换成对象就行了,具体可看一下代码:

在这里插入图片描述


<template>
  <div id="zoning">
  <!--change-on-select是否允许选择任意一级的选项 必须为true 否则触发不了change事件,因为我的首项带child 算是父级-->
  <!--如果change-on-select为false @change不会触发 但会触发active-item-change事件-->
    <el-cascader
      :options="options"
      :clearable="true"
      size="mini"
      ref="cascader"
      @change="handleItemChange"
      @active-item-change="handleItemChange"
      :change-on-select="changeOnSelect"
      :props="props"
    ></el-cascader>
  </div>
</template>

<script>
  export default {
    components: {},
    filters: {},
    props:{
    // 如果该值为false 则只能选择最后一级 
    // 如果该值为true 则可以选择任意层级
    	changeOnSelect:{
			default:false
		}
    },
    data () {
      return {
        options: [],
        props: {
          value: 'main',
          // 显示的文字字段名
          label: 'label',
          // 子层级字段名
          children: 'child'
        }
      }
    },
    methods: {
      /**初始化
       * */
      getZoning () {
        let self = this;
        // 发送请求
        self.$backend.request(self.$api.user.getZoning, {id: 0}).then(res => {
          self.options = res.list
          self.options.map((item, index) => {
            for (let k in item) {
              if (!item[k]) {
                delete item[k]
              }
            }
            // 先让数据变成父级
            item.child = []
            // 手动创建字段表明当前索引 假设arrIndex值为'1-2-3' 即为options[1].child[2].child[3]
            item.arrIndex = index + ''
            // 将当前数据转成字符串放入对象里 当做value值
            item.main = JSON.stringify(item)
          })
        })
      },
      handleItemChange (val) {
      // 因为允许选择任意级,所以在向下选择时,会出现选择多个的情况,造成选中的合并成了一个数组,我这里只让他选择到第三层,页面上最多只会出现选择三个,如果超出了,直接return出去 不需要再动态加载下去了
        if (val.length > 2) return
        //每选中一个选项,相当于将本条数据push到val里,所以索引为val.length - 1的那一项必然是当前点击的那一项
        val = JSON.parse(val[val.length - 1])
        //发送请求
        this.$backend.request(this.$api.user.getZoning, {id: val.roid}).then(res => {
          let data = res.list
          //arrIndex是手动塞进去的索引
          let arrIndex = val.arrIndex
          data.map((item, index) => {
            // 手动创建字段表明当前索引 假设arrIndex值为'1-2-3' 即为options[1].child[2].child[3]
            item.arrIndex = arrIndex + '-' + index
            // 将当前数据转成字符串放入对象里 当做value值
            item.main = JSON.stringify(item)
            // 判断是否是第三层及以上
            if (item.arrIndex.split('-').length < 3) {
              item.child = []
            }
          })
          // 根据父元素的arrIndex判断塞到哪个父元素下
          arrIndex = arrIndex.split('-')
          // 首项键不是child 和for循环里区别开
          let a = this.options[arrIndex[0]]
          for (let i = 1; i < arrIndex.length; i++) {
            a = a['child'][arrIndex[i]]
          }
          
          this.$delete(a, 'child');
          this.$set(a, 'child', data)
        })
      }
    },
    mounted () {
      this.getZoning()
    },
  }
</script>

<style scoped>

</style>

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值