ant-design-vue中 a-select组件 - 加载大量数据造成卡顿--已解决

解决方案借鉴 列表的滚动加载,实现 a-select 数据展示时滚动加载

隐藏问题:

在ant-design-vue 中 ,select 可以通过 输入文字 匹配 数据源中的数据,但是在滚动加载中,如果暂时还没有加载到该条数据,则不能 匹配 到的这条数据。

具体思路如下:

  1. 监听下拉框展开,下拉框展开后,要重置展示的数据,默认每一次新展开就回到初始加载的数据展示。
  2. 监听数据滚动 - @popupScroll
  3. 滚动条改变后 请求数据加载(可以异步请求,也可以一次性请求后,分批加载)
  4. 对滚动加载 做 防抖处理,限制多次请求(lodash/debounce)
  5. 更新下拉框的数据,需要判断已渲染的下拉长度和当前数据源(总数据)的长度,然后 .concat 拼接数组

但这样会有一个隐藏问题,隐藏问题放在最后再说。根据思路解决 “大量数据加载造成的卡顿” 的问题吧。

前置

  • 引入 ant-design-vue ,注意引入的版本,可参考官方说明
    npm i --save ant-design-vue@next

  • 引入  lodash 
     npm i --save lodash
  • 按需引入 ant-design-vue  中的 Select 组件
    // 引入ant-design-vue 的样式
    import 'ant-design-vue/dist/antd.css';
    // 按需引入 Select 组件
    import { Select } from "ant-design-vue";
    
    const app = createApp(App)
    
    app.use(Select)
    
    app.use(store).use(router).mount("#app");

template

    <!--
      allowClear : 支持清除		false:不清除	
      mode :	设置 Select 的模式为多选或标签	'multiple' | 'tags' | 'combobox'
      show-search 	可输入关键词后,对下拉框数据进行搜索
      popupScroll : 下拉列表滚动时的回调
      change : 选中 option,或 input 的 value 变化(combobox 模式下)时,调用此函数
      dropdownVisibleChange : 展开下拉菜单的回调
     -->
    <a-select
      :allowClear="true"
      mode="multiple"
      style="width: 200px"
      placeholder="请选择"
      showArrow
      show-search
      @popupScroll="handlePopupScroll"
      @change="handleChange"
      @dropdownVisibleChange="handleDropdownVisibleChange"
    >
      <a-select-opt-group v-for="item in showList" :key="item">
        <template #label>
          <span> {{ item.letter }} </span>
        </template>
        <a-select-option
          v-for="item in item.letter_arr"
          :key="item"
          :value="item"
          @click="handleClickChange(item)"
          >{{ item }}</a-select-option
        >
      </a-select-opt-group>
    </a-select>

 JS

import { reactive, toRefs } from "vue";
import debounce from "lodash/debounce";
/**
 * 
 * all_Data: 总数据
 * showList:用来展示在 select 下拉框中的数据
 * handlePopupScroll:select 下拉框中的滚动条 滚动时 的回调,做防抖处理
 * handleDropdownVisibleChange:select 下拉框 展开时 的回调监听,open===true,即展开下拉框
 * loadMoreData:滚动条滚动时,showList加载 all_Data 中的数据,更新下拉框的数据
 * handleChange:获取 点击选中的 数据
 * 
*/
export default {
  name: "Home",
  setup() {
    const home_reac = reactive({
      all_Data: [
        {
          letter: "A",
          letter_arr: [
            "a_1",
            "a_2",
            "a_3",
            "a_4",
            "a_5",
            "a_6",
            "a_7",
            "a_8",
            "a_9",
            "a_10",
          ],
        },
        {
          letter: "B",
          letter_arr: [
            "b_1",
            "b_2",
            "b_3",
            "b_4",
            "b_5",
            "b_6",
            "b_7",
            "b_8",
            "b_9",
            "b_10",
          ],
        },
        {
          letter: "C",
          letter_arr: [
            "c_1",
            "c_2",
            "c_3",
            "c_4",
            "c_5",
            "c_6",
            "c_7",
            "c_8",
            "c_9",
            "c_10",
          ],
        },
        {
          letter: "D",
          letter_arr: [
            "d_1",
            "d_2",
            "d_3",
            "d_4",
            "d_5",
            "d_6",
            "d_7",
            "d_8",
            "d_9",
            "d_10",
          ],
        },
        {
          letter: "E",
          letter_arr: [
            "e_1",
            "e_2",
            "e_3",
            "e_4",
            "e_5",
            "e_6",
            "e_7",
            "e_8",
            "e_9",
            "e_10",
          ],
        },
      ],
      showList: [],
    });

    // select - 滚动条 回调 - select数据请求
    const handlePopupScroll = debounce(function () {
      loadMoreData(home_reac.all_Data);
    }, 400);

    // 下拉框打开时 的 回调
    const handleDropdownVisibleChange = (open) => {
      if (open) {
        // 下拉框打开时重置展示的数据
        home_reac.showList = home_reac.all_Data.slice(0, 1);
      }
    };

    // 更新下拉框 展示  的 数据
    const loadMoreData = (dataList) => {
      // 已渲染的下拉列表长度
      const length = home_reac.showList.length;
      // 当前数据源的长度
      const total = dataList.length;
      // 新加载的数据
      let addList = [];
      if (length < total) {
        if (length + 1 <= total) {
          addList = dataList.slice(length, length + 1);
        } else {
          addList = dataList.slice(length, length + (total % 1));
        }
        // 更新下拉框展示的数据
        home_reac.showList = home_reac.showList.concat(addList);
      }
    };

    //数据 筛选
    const handleChange = (item) => {
      console.log("数据筛选", item);
    };

    return {
      ...toRefs(home_reac),
      handlePopupScroll,
      handleChange,
      handleDropdownVisibleChange,
    };
  },
};

这次真是一点也没保留代码,完整的都在这里了~

对了,还有一个隐藏问题,就是:

由于数据是动态加载,当我们第一次请求展示的数据为 “A” 开头的,

此时下拉框中的数据为 A数组 的全部,

那在 input 框中输入关键词搜索时,

将搜索不到 A 以外的其他数据

解决方法暂时有一个方案,但是还没有试验,就是:

当展开下拉框的时候,通过定时器来请求数据,不通过滚动操作来请求加载。

当然,这个方法还没有试验,不确定能不能解决这个问题。 

欢迎关注公众号 “DataShow Charts”呀,我也会在公众号同步发布本篇文章,源码在公众号中~

<think>好的,我现在需要帮助用户解决关于a-tree-select组件的:load-data属性的用法和常见问题。首先,我需要回忆一下用户提供的引用内容,特别是引用[2]和引用[3],因为它们提到了异步加载和懒加载的实现方法。 用户的问题集中在如何使用:load-data属性,可能遇到的常见问题,以及需要示例。根据引用[2],异步加载是通过loadData函数实现的,返回一个Promise,并在数据加载完成后更新树数据。引用[3]和[4]提到了在Vue3中使用el-tree-select时处理懒加载数据回显的问题,特别是需要构造树节点和解决卡顿问题。 首先,我需要解释:load-data的基本用法,给出一个Vue的示例代码,说明如何绑定该属性并处理数据加载。然后,常见问题可能包括数据未更新、回显问题、性能卡顿以及错误处理。例如,数据未更新可能是因为没有正确更新treeData,需要像引用[2]中那样使用setTreeData。回显问题可能涉及默认展开节点,如引用[3]提到的default-expanded-keys属性,需要确保节点已加载。性能方面,引用[4]提到检查节点属性和避免不必要的渲染,可能需要优化load-data函数的执行。 另外,需要注意用户提到的a-tree-selectAnt Design Vue组件,而引用中有部分是关于Element Plus的,但核心概念类似。需要确保示例代码符合Ant Design Vue的语法,比如使用load-data而不是loadData,以及正确的事件处理。 可能还需要提醒用户关于Promise的正确使用,确保在数据加载完成后调用resolve,避免一直处于加载状态。同时,处理加载失败的情况,提供错误反馈,如引用[2]中的示例用setTimeout模拟异步请求,实际应用中可能需要替换为真实的API调用。 总结步骤:1. 解释:load-data的作用;2. 提供基础用法示例;3. 分析常见问题及解决方法;4. 引用相关引用内容支持解答。确保回答结构清晰,覆盖用户可能遇到的问题,并参考提供的引用内容给出具体建议。</think>### 关于 a-tree-select 的 `:load-data` 属性用法详解 #### 一、基础用法 `:load-data` 是 Ant Design Vue 树选择组件(`a-tree-select`)中用于**异步加载子节点数据**的属性。通过绑定一个异步函数,当用户展开未加载的父节点时触发数据加载,适用于大数据量或动态层级数据的场景。 **示例代码:** ```vue <template> <a-tree-select v-model="selectedValue" style="width: 100%" :tree-data="treeData" :load-data="loadData" placeholder="请选择" /> </template> <script> export default { data() { return { selectedValue: null, treeData: [ { title: &#39;根节点&#39;, value: &#39;root&#39;, key: &#39;root&#39;, isLeaf: false } ] }; }, methods: { async loadData(treeNode) { return new Promise(resolve => { // 模拟异步请求(替换为真实API) setTimeout(() => { const newChildren = [ { title: `子节点-${Math.random().toString(36).substr(2, 4)}`, value: &#39;child&#39;, key: `${Date.now()}`, isLeaf: true } ]; treeNode.dataRef.children = newChildren; this.treeData = [...this.treeData]; // 触发视图更新[^2] resolve(); }, 1000); }); } } }; </script> ``` #### 二、核心问题与解决方案 1. **数据未更新问题** - **现象**:加载子节点后树结构未刷新。 - **解决**:必须通过重新赋值 `treeData` 触发响应式更新(如示例中的 `this.treeData = [...this.treeData]`)[^2]。 2. **节点回显异常** - **场景**:已选节点因未加载导致无法显示标签。 - **方案**:预加载节点路径数据,或结合 `default-expanded-keys` 提前展开路径(类似 Vue3 中 `default-expanded-keys` 的用法)[^3]。 3. **性能优化** - **卡顿处理**:检查 `load-data` 函数执行时间,避免阻塞主线程。可通过分页加载或减少单次请求数据量优化[^4]。 - **节点属性**:确保每个节点明确标注 `isLeaf`,避免不必要的加载图标[^4]。 4. **错误处理** ```javascript loadData(treeNode) { return new Promise((resolve, reject) => { fetchAPI().then(data => { // 更新数据并 resolve() }).catch(error => { reject(); this.$message.error(&#39;加载失败&#39;); }); }); } ``` #### 三、典型应用场景 - 文件系统目录选择 - 组织架构树(动态加载部门成员) - 分类层级数据(如电商商品类目)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值