Vant Cascader省市区数据太多,点一次掉一次子级数据

文章讨论了如何解决后端接口响应四级及以上地区数据过慢的问题,通过后端返回一级数据,前端使用Cascader组件分步加载子级,以提高性能。作者还展示了vant-address组件的使用和父子级数据处理的JavaScript方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:之前是后端把所有数据都返回(平级数据),然后前端自己写方法去处理成父子级关系来用的:js方法将省市区的平级数据转换成父子树状数据

因为之前省市区最多只有三级数据,总共不到四千条数据,所以接口返回的速度还好

最近需求是 省市区县,有四级或更多级,数据实在是太多(四万多条数据),如果后端一次性返回,速度实在是太慢,十几秒后才返回,不太行,所以就新出了个接口

解决方案:后端返回一级数据,点一下父级,掉一下接口获取子级数据

父级

vant-address 是封装组件

<template>
    <div>
        <van-button color="linear-gradient(to right, #ff6034, #ee0a24)" @click="showPop">选择地址</van-button>
        <div>选择的地址名字:{{formData.areaName}}</div>
        <div>选择的地址code:{{formData.areaCode}}</div>
        <vant-address :is-areashow="isAreaVisible" @closepop="closePop" @closecancel="closeCancel"></vant-address>
    </div>
</template>
<script>
import VantAddress from '@/路径/vant-address.vue';
export default {
    data () {
        return {
            isAreaVisible: false, // 组件是否显示
            formData: {
                areaCode: '',
                areaName: ''
            }
        }
    },
    components:{
        VantAddress
    },
    methods: {
        showPop(){
            this.isAreaVisible = !this.isAreaVisible
        },
        closePop(areaName,areaIds){
            // 点击 确定事件,获取选中的name和code,并关闭弹框
            console.log(areaName,areaIds);
            this.formData.areaCode = areaIds
            this.formData.areaName = areaName
            this.isAreaVisible = false
        },
        closeCancel(){
            // 点击 取消事件,关闭弹框
            this.isAreaVisible = false
        },

    }
};
</script>
<style scoped='scoped' lang='scss'>
</style>

子级

<!--选择位置组件-->
<template>
  <div>
    <van-popup v-model="isAreashow" round position="bottom">
      <div class="queding" @click="addressSubmit">确定</div>
      <van-cascader
        title="请选择所在地区"
        style="padding-bottom: 80px;"
        :options="options"
        v-model="cascaderValue"
        :field-names="customFieldName"
        @close="onClose"
        @change="onChangeArea"
        @finish="onFinish"
      />
    </van-popup>
  </div>
</template>
<script>

import { areaParentData } from '@/api/地址'; // 接口地址
export default {
  props: {
    isAreashow: {
      type: Boolean,
      default: false
    }
  },
  data(){
    return{
      options: [],
      isAreaVisible: false,
      customFieldName: {
        text: 'name',
        value: 'areaId',
        children: 'children',
        code: 'code'
      },
      cascaderValue: '',
      divisionIds: '',
      divisionNames: ''
    }
  },

  mounted(){
    this.getAreaList();
  },

  methods:{
    addressSubmit(){
      // 确定事件,调用父级的closepop事件,传参name和code
      this.$emit('closepop',this.divisionNames,this.divisionIds)
    },
    onClose(){
      // 取消事件,调用父级的closecancel事件
      this.$emit('closecancel')
    },
    onFinish({ selectedOptions }) {
      // 选中的内容,赋值给name和code
      this.divisionNames = selectedOptions.map(option => option.name).join('-')
      this.divisionIds = selectedOptions.map(option => option.areaId).join(',')
    },
    //获取地区数据
    async getAreaList(){
        // 后端接口,获取省市区一级数据
        const res = await areaParentData({
            parentCode: 0 // 传0是一级数据
        })
        this.ProvinceList = res.data
        this.options = [] // 先清空一下,不然会有重复数据
        res.data.forEach(item => {
          this.options.push({
            name: item.name,
            areaId: item.areaId,
            code: item.code,
            childrenStatus: item.childrenStatus, // 接口返回的是否有子级
            children: item.children || null// 这个很关键
          })
        });
    },
    onChangeArea({ value, selectedOptions, tabIndex }) {
      console.log(value, selectedOptions, tabIndex);
      // value是选中当前列的value(areaId),selectedOptions是选中的数组,tabIndex是选中数组的第几个
      // 需要后台接口返回children数据
      // 拿到数据后,动态添加
      if(selectedOptions[selectedOptions.length-1].childrenStatus){
      // 如果选中数组的最后一个的childrenStatus为true,说明它有子级,就掉接口
        areaParentData({
          parentCode: selectedOptions[selectedOptions.length-1].code // 取得是选中数组里最后一个对象的code
        }).then(res => {
          // 接口返回的数据也就是res.data 赋值给那条数据当children
          this.addTree(selectedOptions, res.data, value)
        })
      }
    },
    addTree(selectedOptions, children, id) {
      selectedOptions.forEach(item => {
        if (item.areaId === id) {
          item.children = children
        }
      })
    }
  }
}
</script>
<style lang="scss" scoped>
  .van-cascader{
    color: #323233 !important;
  }
  .queding{
    color: #fff;
    background-color: #ff4949;
    position: fixed;
    bottom: 0;
    width: 90%;
    // padding: 10px 20px;
    height: 36px;
    line-height: 36px;
    border-radius: 4px;
    font-size: 14px;
    text-align: center;
    z-index: 10;
    left: 50%;
    transform: translate(-50%, -50%);
  }
</style>

父级页面样式:

省市区组件是封装组件

我用的 vant 的 Cascader 组件,封装成一个组件了,点击确定事件和取消事件用的父子事件

因为可能选择二级就完成了,也可能选择三级、四级,所以最下面加了个确定按钮,点击确定才算完成

接口返回的第一级数据

{
  "areaId": "1", // 后面需要传给后端的id
  "parentCode": "0",
  "code": "1100001", // 掉下一级数据传给后端的code
  "name": "北京",
  "status": 0,
  "level": 0,
  "prefixCode": "B",
  "ifHot": 0,
  "logo": "/beijing.jpeg",
  "areaIdGroup": "",
  "areaNameGroup": "",
  "children": "",
  "childrenStatus": true // 是否有子级,如果是true就说明有子级,false就没有子级
},
{
  "areaId": "37",
  "parentCode": "0",
  "code": "130000",
  "name": "河北省",
  "status": 0,
  "level": 0,
  "prefixCode": "H",
  "ifHot": 0,
  "logo": "/heibei.jpg",
  "areaIdGroup": "",
  "areaNameGroup": "",
  "children": "",
  "childrenStatus": true
}

 接口返回的二级数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值