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

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

背景:之前是后端把所有数据都返回(平级数据),然后前端自己写方法去处理成父子级关系来用的: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
<think>好的,我现在要解决用户在使用Vant Cascader组件时遇到的异步加载数据导致弹窗过早关闭的问题。首先,我需要理解用户的问题场景。用户提到当数据量大时,接口响应慢,前端渲染也变慢,导致体验不好,所以他们采用了异步加载。但是,在数据还没有返回的时候,Cascader组件可能因为判断没有而自动关闭弹窗,这显然不是用户期望的行为。 接下来,我需要回忆Vant Cascader组件的工作机制。根据文档,Cascader组件在每次选择某一后,会检查当前选中项是否有children属性。如果没有,就会认为没有下一,自动关闭弹窗。但在异步加载的情况下,数据可能还在请求中,此时children可能还未被填充,导致组件误判,关闭弹窗,这就是问题的根源。 那如何防止在数据加载完成前弹窗关闭呢?首先想到的是,在异步加载数据的过程中,需要让组件保持加载状态,直到数据返回。可能需要手动控制弹窗的显示状态,或者利用组件提供的loading状态。 查阅Vant的文档,发现Cascader组件有一个`lazy`属性,用于开启异步加载模式。同时,每个节可以通过`loading`属性显示加载状态。当用户击某一节时,触发`lazy-load`事件,此时需要在该事件的处理函数中,将当前节标记为加载中,并发送异步请求获取数据。请求返回后,将数据添加到该节的children中,并关闭loading状态。 但是,用户的问题是在数据未返回前,组件可能因为children不存在而关闭弹窗。因此,可能需要确保在加载过程中,组件不会认为没有。可能的解决方案是,在开始加载时,临时给当前节添加一个空的children数组,或者标记为正在加载,这样组件会认为还有,从而保持弹窗开启。 另外,用户提到后端需要返回是否还有下一的判断。这可能涉及到在每次请求数据时,后端返回的数据结构需要包含一个字段(如hasNext),前端根据这个字段来决定是否继续加载,或者结束。如果后端没有正确返回这个字段,可能会导致组件提前结束。 所以,具体的步骤可能是: 1. 在击节时,触发异步加载。 2. 在加载开始前,设置该节的loading状态为true,这样Cascader组件会显示加载中的状态,并保持弹窗开启。 3. 发送异步请求获取数据。 4. 请求完成后,将数据添加到当前节的children中,并设置loading为false。 5. 如果后端返回的数据中没有children,或者hasNext为false,则移除loading状态,让组件正常关闭弹窗。 同时,需要注意在数据请求过程中,用户可能进行其他操作,比如关闭弹窗,这时候可能需要阻止默认的关闭行为,直到数据加载完成。不过,Vant组件可能没有直接提供这样的控制,所以可能需要结合组件的open属性,手动控制弹窗的显示状态。 另外,还需要处理加载失败的情况,避免因为请求失败导致loading状态一直存在,弹窗无法关闭。这时候需要在catch中处理错误,并取消loading状态。 总结可能的解决方案: - 使用lazy-load事件,结合loading状态。 - 在异步加载期间保持loading为true,直到数据返回。 - 确保后端返回的数据结构正确,包含是否有下一的标志。 - 可能需要手动控制弹窗的显示,防止自动关闭。 现在需要验证这些思路是否正确。比如,是否在设置loading为true时,组件会自动保持弹窗开启?查看Vant的文档,Cascader的lazy-load方法中,当调用回调函数并传入children时,如果children为空数组,组件会认为没有。但如果在加载过程中,节有loading: true,组件应该会等待加载完成,不会关闭弹窗。因此,关键是在加载过程中正确管理节的loading状态和children。 所以,正确的代码示例应该是在lazy-load事件处理中,首先设置node的loading为true,然后发起请求,请求成功后,将返回的数据作为children,并设置loading为false。如果数据为空,则children设为空数组,这样组件会自动关闭弹窗。 但用户的问题可能出现在,当数据请求较慢时,击后由于没有及时设置children,组件认为没有而关闭。因此,可能需要确保在击节后,立即将节标记为loading,并且在数据返回前,保持该状态,这样弹窗就不会关闭。 因此,解决方案的核心是正确使用loading状态,并在异步请求处理中管理节的children和loading状态。同时,确保后端返回的数据结构正确,以便前端判断是否有下一数据。 最后,可能需要检查代码实现是否正确,比如是否正确处理了异步回调,是否在请求结束后正确更新了节的children和loading状态。此外,可能需要添加加载中的提示,提升用户体验。</think>### 解决方案 针对Vant Cascader组件在异步加载数据时弹窗过早关闭的问题,核心思路是通过**手动控制节状态**,确保数据加载完成前弹窗保持开启。以下是具体步骤: --- #### 1. **开启异步加载模式** 在组件中启用`lazy`属性,并绑定`lazy-load`事件处理异步加载逻辑: ```html <van-cascader :lazy="true" :value="selectedValue" @lazy-load="onLazyLoad" /> ``` --- #### 2. **控制节加载状态** 在`lazy-load`事件中,通过设置节的`loading`属性为`true`,强制组件进入加载状态,避免弹窗关闭。数据返回后,根据结果更新并关闭加载状态: ```javascript async onLazyLoad(node, resolve) { // 标记为加载中,防止弹窗关闭 node.loading = true; try { // 异步请求数据 const children = await fetchChildrenData(node.value); // 若后端返回无,需显式设置children为空数组 resolve(children.length > 0 ? children : []); // 若后端返回"是否有下一"标记(如hasNext),可动态处理 // if (children.hasNext) resolve(children.list); // else resolve([]); } catch (error) { resolve([]); // 异常时结束加载 } finally { node.loading = false; // 关闭加载状态 } } ``` --- #### 3. **后端数据格式要求** 确保后端返回的数据包含**是否还有下一**的标记(如`hasNext`),或直接返回列表。若为空数组,组件会自动关闭弹窗[^1]: ```json // 示例:返回列表 { "list": [ { "text": "1", "value": 1 }, { "text": "2", "value": 2 } ] } // 或返回是否还有下一 { "hasNext": true, "list": [...] } ``` --- #### 4. **添加加载提示(可选)** 通过CSS或组件配置,在加载时显示提示(如“加载中...”),提升用户体验: ```css .van-cascader__loading { padding: 10px; color: #999; text-align: center; } ``` --- ### 关键逻辑说明 - **`loading`状态的作用**:当`node.loading = true`时,组件会认为当前节仍在加载中,弹窗不会关闭[^1]。 - **空的处理**:若异步加载后为空数组(`resolve([])`),组件会判定无下一并关闭弹窗。 - **错误处理**:请求失败时需调用`resolve([])`,避免组件处于永久加载状态。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值