antdesginVue VUE3.0 Cascader 级联选择省市区(县)镇四级联动 动态加载数据(组件封装)

antdesginVue VUE3.0 Cascader 级联选择省市区(县)镇四级联动 动态加载数据

第一步:获取数据

<template>
  <a-cascader
    style="width: 100%"
    v-model:value="cityVal"
    :options="options"
    :load-data="loadData"
    placeholder="请选择"
    change-on-select
  />
template>

第一步 异步加载数据

<script lang="ts" setup>
import { ref, watch } from 'vue'
import type { CascaderProps } from 'ant-design-vue'
import { getDistrict } from '@/api'
  interface props<T> {
    province: T
    city: T
    county: T
  }
  const Props = withDefaults(defineProps<props<string>>(), {
    province: '',
    city: '',
    county: '',
  })
  const emit = defineEmits<{
    (event: 'getcityVal', val: Array<string>): void
  }>()
  let cityVal = ref<Array<string>>([])
  const options = ref<CascaderProps['options']>()
  const key = ref<number>(0)
  let twoCityObj = ref<any | null>(null)

  const loadData: CascaderProps['loadData'] = (selectedOptions) => {
    const targetOption = selectedOptions[selectedOptions.length - 1]
    targetOption.loading = true
    setTimeout(() => {
      targetOption.loading = false
      getCityList(targetOption.name, 'city', targetOption)
    }, 100)
  }

  async function getCityList(value: string, name: String, targetOption?: any) {
    let res: any = await getDistrict({ keywords: value, sub_district: 1 })
    if (res.code === 20000) {
      let arr = res.data.districts[0].districts
      arr.forEach((item: any) => {
        item.value = item.name
        item.label = item.name
        item.isLeaf = item.level === 'street' ? true : false
      })
      if (name == 'all') {
        options.value = arr
      } else if (name == 'city') {
        targetOption.children = arr
      }
    } else {
      console.log('获取国内行政区域失败')
    }
  }
  if (!options.value || options.value.length === 0) {
    getCityList('', 'all')
  }
</script>

第二步 数据回显

<script lang="ts" setup>
  import { ref, watch } from 'vue'
  import type { CascaderProps } from 'ant-design-vue'
  import { getDistrict } from '@/api'

  interface props<T> {
    province: T
    city: T
    county: T
    town: T
  }

  const Props = withDefaults(defineProps<props<string>>(), {
    province: '',
    city: '',
    county: '',
    town: '',
  })

  const emit = defineEmits<{
    (event: 'getcityVal', val: Array<string>): void
  }>()

  let cityVal = ref<Array<string>>([])
  let twoCityObj = ref<any | null>(null)
  const options = ref<CascaderProps['options']>()
  const key = ref<number>(0)

  const loadData: CascaderProps['loadData'] = (selectedOptions) => {
    const targetOption = selectedOptions[selectedOptions.length - 1]
    targetOption.loading = true
    setTimeout(() => {
      targetOption.loading = false
      getCityList(targetOption.name, 'city', targetOption)
    }, 100)
  }

  async function getCityList(value: string, name: String, targetOption?: any) {
    let res: any = await getDistrict({ keywords: value, sub_district: 1 })//keywords:地名,sub_district:为1 是只查询一级数据
    if (res.code === 20000) {
      let arr = res.data.districts[0].districts
      arr.forEach((item: any) => {
        item.value = item.name
        item.label = item.name
        item.isLeaf = item.level === 'street' ? true : false
      })
      if (name == 'all') {
        options.value = arr
        if (Props.province) {
          cityVal.value[0] = Props.province
          key.value++
        }
      } else if (name == 'city') {
        if (targetOption) {
          targetOption.children = arr
        }
        if (key.value === 2) {
          cityVal.value[1] = Props.city
          key.value++
          twoCityObj.value = arr?.find((item: any) => {
            return item.value === Props.city
          })
        } else if (key.value === 4) {
          cityVal.value[2] = Props.county
          key.value++
          twoCityObj.value = arr?.find((item: any) => {
            return item.value === Props.county
          })
        } else if (key.value === 6) {
          cityVal.value[3] = Props.town
        }
      }
    } else {
      console.log('获取国内行政区域失败')
    }
  }

  if (!options.value || options.value.length === 0) {
    getCityList('', 'all')
  }
  watch(
    () => key.value,
    (v) => {
      if (v == 1) {
        key.value++
        let obj = options.value?.find((item) => {
          return item.value === Props.province
        })
        getCityList(Props.province, 'city', obj)
      } else if (v == 3) {
        key.value++
        getCityList(Props.city, 'city', twoCityObj.value)
      } else if (v == 5) {
        key.value++
        getCityList(Props.county, 'city', twoCityObj.value)
      }
    },
    {
      deep: true,
    }
  )
  watch(
    () => cityVal.value,
    () => {
      emit('getcityVal', cityVal.value)
    }
  )
  watch(
    () => Props.province,
    (v) => {
      if (options.value && options.value.length > 0) {
        if (v) {
          cityVal.value[0] = v
          key.value = 1
        } else {
          cityVal.value = []
          key.value = 0
        }
      }
    },
    { deep: true }
  )
</script>

此代码的需要数据格式:
antdesginVue VUE3.0 Cascader 级联选择省市区(县)镇四级联动 动态加载数据(组件封装)_第1张图片
父组件(主要代码):

<a-form-item>
 <template #label>
     <span style="color: red">* span>
     <span>所在区域span>
   template>
   <CityCascader
     :province="formState.province"
     :city="formState.city"
     :county="formState.county"
     :town="formState.town"
     @getcityVal="getcityVal"
   >CityCascader>
 a-form-item>
 //获取区域
  async function getcityVal(data: any) {
    if (data && data.length > 0) {
      ;[
        formState.value.province,
        formState.value.city,
        formState.value.county,
        formState.value.town,
      ] = data
    }
  }

你可能感兴趣的:(vue,javascript,vue.js,前端)