vant Cascader 级联选择 异步加载

<template>
  <div class="cascader">
    <van-field v-model="fieldValue"
      is-link
      readonly
      :label="label"
      :required="required"
      :rules="rules"
      :placeholder="placeholder"
      @click="show = true" />
    <van-popup v-model="show"
      round
      position="bottom">
      <van-cascader v-model="cascaderValue"
        :title="label"
        :options="options"
        @change="selectChange"
        active-color="#1989fa"
        :field-names="fieldNames"
        @close="show = false"
        @finish="onFinish" />
    </van-popup>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: () => ''
    },
    isCode: {
      type: Boolean,
      default: () => false
    },
    name: {
      type: String,
      default: () => '默认'
    },
    valueKey: {
      type: String,
      default: () => 'value'
    },
    labelKey: {
      type: String,
      default: () => 'label'
    },
    label: {
      type: String,
      default: () => '默认'
    },
    prop: {
      type: String,
      default: () => ''
    },
    url: {
      type: String,
      default: () => ''
    },
    superCodeVal: {
      type: String,
      default: () => ''
    },
    required: {
      type: Boolean,
      default: () => false
    },
    rules: {
      type: Array,
      default: () => []
    },
    placeholder: {
      type: String,
      default: ''
    },
    lastLevel: {
      type: Number,
      default: () => 3
    }
  },
  data() {
    return {
      show: false,
      fieldValue: '',
      cascaderValue: '',
      fieldNames: {
        text: 'dictName',
        value: 'dictCode'
      },
      options: [],
      isExecute: 1,
      tileArr: []
    }
  },
  methods: {
    // 全部选项选择完毕后,会触发 finish 事件
    onFinish({ selectedOptions }) {
      // this.show = false
      if (this.level > 0) {
        this.show = false
      }

      if (this.isCode) {
        this.fieldValue = selectedOptions.map((option) => `${option.dictName}(${option.dictCode})`).join('/')
      } else {
        const fieldValue = selectedOptions.map((option) => option.dictName).join(',')
        if (fieldValue.split('/').length) {
          this.fieldValue = fieldValue
          this.$emit('input', fieldValue)
          return
        }
        this.fieldValue = fieldValue.split(',').join('/')
      }
      this.$emit('input', this.fieldValue.split('/') + '')
    },
    selectChange({ value, selectedOptions, tabIndex, index }) {
      this.level = tabIndex > 0 ? tabIndex - 1 : 0
      // 判断循环了多少次 并且是回显还是重新选择
      if (this.isExecute >= this.lastLevel + 1 && !selectedOptions) {
        return
      }
      // 判断重新选择的个数是否大于传入的lastLevel
      if (selectedOptions && selectedOptions.length >= this.lastLevel) {
        return
      }
      if (this.url) {
        this.$http.post(this.url, { level: this.level, parentCode: value }).then((res) => {
          // 检查重复项
          if (!this.deWeightFour(this.tileArr, res.data)) {
            this.tileArr.push(...res.data)
          }
          if (res.data && res.data.length) {
            this.isExecute++
            this.getDicData(index++)
          }
          this.$set(this, 'options', this.setTreeData(this.tileArr))
        })
      } else {
        console.error('请配置Url地址')
      }
    },
    // 遍历数据并添加children
    setTreeData(source) {
      const cloneData = JSON.parse(JSON.stringify(source)) // 对源数据深度克隆
      return cloneData.filter((father) => {
        // 循环所有项,并添加children属性
        const branchArr = cloneData.filter((child) => father.dictCode === child.parentCode) // 返回每一项的子级数组
        branchArr.length > 0 && (father.children = branchArr) // 给父级添加一个children属性,并赋值
        return father.parentCode === this.superCodeVal // 返回第一层
      })
    },
    // 判断要添加的值是否在这个数组李是否有重复
    deWeightFour(sourceData, inspectData) {
      const source = sourceData.map((item) => item.id)
      return inspectData.map((item) => source.includes(item.id)).includes(true)
    },
    getDicData(tabIndex = 0) {
      // eslint-disable-next-line no-useless-escape
      const str = this.value.split(',').map((item) => item.replace(/\([^\)]*\)/g, ''))
      const items = str[tabIndex]
      this.tileArr.forEach((item) => {
        if (item.dictName === items) {
          console.log(item.dictCode)
          this.cascaderValue = item.dictCode
          this.selectChange({ value: item.dictCode, tabIndex: 0, index: ++tabIndex })
        }
      })
    }
  },
  created() {
    this.fieldValue = this.value.split(',').join('/')
    this.selectChange({ value: this.superCodeVal, tabIndex: 1 })
  },
  watch: {
    value: {
      handler(v) {
        this.fieldValue = this.value.split(',').join('/')
      }
    },
    show: {
      handler(v) {
        if (v && this.fieldValue && this.isExecute) {
          this.getDicData()
        }
      }
    }
  }
}
</script>

<style>
</style>

上一篇:小程序的组件使用传参


下一篇:uni-app中引用vant的正确姿势,个人只用过H5