Cascader 级联选择器 懒加载情况实现单选/多选默认值问题

2,367 阅读1分钟

element ui组件库的Cascader级联选择器在懒加载情况下,如果想要开始就显示默认值,由于options中没有对应选中的数据,可能导致默认显示有问题。解决方法有很多,常用的解决方法就是提前请求数据,拼好options,然后再赋值。今天我们来用另一种方法解决这个问题,这个方法不需要将赋初始值的代码放在后面,就按照正常input框赋初始值一样即可。话不多说,往下看。 注意:目前实现的是2级联动,2级以上没有试过

单选默认值解决

解决思路:手动触发组件源码的懒加载方法

首先,页面进来以后,要手动的调用组件内部的懒加载方法,传递的参数也是需要到组件内部去找的

    for (let item of this.$refs.provinceCity.panel.menus[0]) {
        if (item.value === val[0]) {
          // item.func = this.waitItemExecution
          // 手动触发组件源码的懒加载方法,参数为node结点
          this.$refs.provinceCity.panel.lazyLoad(item)
          return
        }
      }

调用完懒加载的方法后,数据还是不能回显,原因是内部方法没有调用全,在懒加载方法后面再手动调用两个内部方法即可,可统一封装成一个方法

    waitItemExecution (val) {
      this.$refs.provinceCity.panel.handleExpand(val)
      this.$refs.provinceCity.computePresentText()
    }

完整代码

只展示有关代码

<template>
    <el-cascader ref="provinceCity" v-model="provinceCityCode" show-all-levels :options="this.allProvince" :props="provinceAndCityProps" filterable></el-cascader>
</template>
<script>
export default {
    data(){
        return{
            // 选中的省市
            provinceCityCode: ['provinceCode', 'cityCode'],
            // 所有省
            allProvince: [],
            provinceAndCityProps: {
                lazy: true,
                lazyLoad: (node, resolve) => {
                  this.getCityByProvince(node, resolve)
                },
                value: 'code',
                label: 'name'
              }
        }
    },
    created () {
        // 查询所有省
        this.queryAllProvince()
    },
    mounted: function () {
        // 由于handleProvinceCityDefault方法中用到了ref所以要等结点绘制好后再调用所以放在mounted中
        this.handleProvinceCityDefault()
    },
    // 方法中调用的service方法就不给出了,调用自己的即可
   methods: {
    // 查询所有省
    async queryAllProvince () {
      const res = await queryAllProvinceService()
      if (res && res.success) {
        this.allProvince = res.data || []
      }
    },
    // 首次默认触发调用懒加载
    handleProvinceCityDefault () {
      let val = this.provinceCityCode
      for (let item of this.$refs.provinceCity.panel.menus[0]) {
        if (item.value === val[0]) {
          // item.func = this.waitItemExecution
          // 手动触发组件源码的懒加载方法
          this.$refs.provinceCity.panel.lazyLoad(item)
          return
        }
      }
    },
    // 动态获取市信息
    async getCityByProvince (node, resolve) {
      const { value } = node
      if (!value) {
        return null
      }
      const result = await getCityByProvinceService({
        parentCode: value
      })
      if (result && result.success) {
        resolve(result.data && result.data.length ? result.data.map(item => ({...item, leaf: true})) : [])
      } else {
        this.$message.error(result.message)
        resolve(false)
      }
      // 调用内部方法实现数据回显,如果不调用此方法,虽然懒加载调用了,但是数据还是不能回显到input框
      this.waitItemExecution(node)
    },
    waitItemExecution (val) {
      this.$refs.provinceCity.panel.handleExpand(val)
      this.$refs.provinceCity.computePresentText()
    }
   }
}
</script>

这样,懒加载情况下单选展示默认值功能就实现了。下面我们来看看多选默认值展示吧。

多选默认值解决

解决思路:思路同上,首先手动触发组件源码的懒加载方法,只是后面调用的内部方法不同而已

首先,页面进来以后,要手动的调用组件内部的懒加载方法,传递的参数也是需要到组件内部去找的

    for (let item of this.$refs.provinceCity.panel.menus[0]) {
        // ['一级code1', '一级code2']为你默认值中的一级数据即要展开(加载数据)的一级数据,这里面怎样写都可以,目的是调用选中数据中一级数据的懒加载方法
        if (['一级code1', '一级code2'].includes(item.value)) {
          // item.func = this.waitItemExecution
          // 手动触发组件源码的懒加载方法,参数为node结点
          this.$refs.provinceCity.panel.lazyLoad(item)
        }
      }

调用完懒加载的方法后,数据还是不能回显,原因是内部方法没有调用全,在懒加载方法后面再手动调用3个内部方法即可,可统一封装成一个方法

    waitItemExecution (val) {
      this.$refs.provinceCity.panel.handleExpand(val)
      this.$refs.provinceCity.panel.syncMultiCheckState()
      this.$refs.provinceCity.computePresentContent()
    }

完整代码

只展示有关代码

<template>
    <el-cascader ref="provinceCity" v-model="provinceCityCode" show-all-levels :options="this.allProvince" :props="provinceAndCityProps" filterable></el-cascader>
</template>
<script>
export default {
    data(){
        return{
            // 选中的省市
            provinceCityCode: [['provinceCode1', 'cityCode1'], ['provinceCode2', 'cityCode2']],
            // 所有省
            allProvince: [],
            provinceAndCityProps: {
                multiple: true
                lazy: true,
                lazyLoad: (node, resolve) => {
                  this.getCityByProvince(node, resolve)
                },
                value: 'code',
                label: 'name'
              }
        }
    },
    created () {
        // 查询所有省
        this.queryAllProvince()
    },
    mounted: function () {
        // 由于handleProvinceCityDefault方法中用到了ref所以要等结点绘制好后再调用所以放在mounted中
        this.handleProvinceCityDefault()
    },
    // 方法中调用的service方法就不给出了,调用自己的即可
   methods: {
    // 查询所有省
    async queryAllProvince () {
      const res = await queryAllProvinceService()
      if (res && res.success) {
        this.allProvince = res.data || []
      }
    },
    // 首次默认触发调用懒加载
    handleProvinceCityDefault () {
      // 获取选中数据的一级数据
      let val = this.provinceCityCode.map(item=>item[0])
      // 一级数据去重,最终为['provinceCode1', 'provinceCode2']
      let uniqueArray = val.reduce((unique, item) => { unique.includes(item) ? unique : [...unique, item] }, [])
      // 循环
      for (let item of this.$refs.provinceCity.panel.menus[0]) {
        if (uniqueArray.includes(item.value)) {
          // item.func = this.waitItemExecution
          // 手动触发组件源码的懒加载方法,参数为node结点
          this.$refs.provinceCity.panel.lazyLoad(item)
        }
      }
    },
    // 动态获取市信息
    async getCityByProvince (node, resolve) {
      const { value } = node
      if (!value) {
        return null
      }
      // 解决点击叶子结点调用接口问题
      if (hasChildren) {
          const result = await getCityByProvinceService({
            parentCode: value
          })
          if (result && result.success) {
            resolve(result.data && result.data.length ? result.data.map(item => ({...item, leaf: true})) : [])
          } else {
            this.$message.error(result.message)
            resolve(false)
          }
      } else {
          this.$message.error(result.message)
          resolve(false)
        }
      // 调用内部方法实现数据回显,如果不调用此方法,虽然懒加载调用了,但是数据还是不能回显到input框
      this.waitItemExecution(node)
    },
    waitItemExecution (node) {
      this.$refs.provinceCity.panel.handleExpand(node)
      this.$refs.provinceCity.panel.syncMultiCheckState()
      this.$refs.provinceCity.computePresentContent()
    },
   }
}
</script>

欢迎大家指教,共同进步,创作不易

参考:www.jb51.net/article/262…