需求

  • ant-design-vue select下拉列表当中动态加载列表,当滚动到最后的时候继续加载,没有数据了就不加载了
  • 这里的defHttp就是axios的二次封装,你们可以替换为axios就可以
  • 效果的话就不展示了,因为数据都是后台请求的~

做法

  • 用到的ant design vue组件有
    • a-spin加载圈圈的
    • a-select下拉列表
    • a-empty空状态的(这里自定义了空状态,使其文字替换为加载圈圈)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//必须要写
const VNodes = (_, { attrs }) => {
return attrs.vnodes;
}
<a-select
v-model:value="searchForm.userIds"
allow-clear
mode="multiple"
@dropdownVisibleChange="handleDropDownVisibleChange"
@popupScroll="handlePopupScroll"
:max-tag-count="1"
:max-tag-text-length="2"
placeholder="请选择">
<a-select-option v-for="item in dropDownData.options" :key="item.id" :value="item.id">
{{item.name}}
</a-select-option>

<template #dropdownRender="{ menuNode: menu }">
<a-empty v-if="dropDownData.isLoading">
<template #description>
<span><a-spin /></span>
</template>
</a-empty>
<a-empty v-else-if="dropDownData.options.length === 0">
<template #description>
暂无数据
</template>
</a-empty>
<!--显示结果-->
<!--v-nodes必须要写在最后面,这个代表要渲染的下拉列表数据-->
<template v-else>
<v-nodes :vnodes="menu" />
</template>
</template>
</a-select>


//要发送给后台的数据
const searchForm = ref<SearchFormTypes>({
userName:'',
userIds:[],//记录用户选取的下拉列表数据
});

/* 下拉列表请求-初次的时候 */
const handleDropDownVisibleChange = async (open) => {
if(open && dropDownData.value.options.length === 0 ){
//初次加载
const result = await defHttp.post(({url:'/xxxx',params:{userName:searchForm.value.userName,...dropDownData.value.pagination}}));
dropDownData.value.pagination.total = result.total ?? 0;
dropDownData.value.isLoading = false;
//从结果中map获取列表数据
dropDownData.value.options = result?.list?.map(item => ({
id:item.id ?? 0,
name:item.name ?? "",
})) ?? [];
}
}

/* 下拉滚动 */
const handlePopupScroll = async (e) => {
//已经有的下拉项目 大于等于后台返回的下拉项总长度,那么就返回不请求了
if(dropDownData.value.options.length >= dropDownData.value.pagination.total) return;
const { scrollHeight, scrollTop, clientHeight } = e.target;
if (scrollHeight - scrollTop === clientHeight) {
//到达了底部,请求数据
dropDownData.value.pagination.page++;//分页器自增1
const result = await defHttp.post(({url:'/xxxxx',params:{userName:searchForm.value.userName,...dropDownData.value.pagination}}));
//从结果中map获取列表数据
const temp = result?.list?.map(item => ({
id:item.id ?? 0,
name:item.name ?? "",
})) ?? [];
//注意顺序,这里是先结构之前的,在结构之后的
dropDownData.value.options = [...dropDownData.value.options,...temp];
}
}

// 下拉列表
const dropDownData = ref<dropDownDataTypes>({
options:[],//下拉项列表
pagination:{
page:1,
pageSize:10,
total:0,//用于记录数据总长度,后期判断是否还继续加载
},//分页器下拉的
isLoading:true, //是否正在加载数据
})

回调说明和其他的一些说明

  • @dropdownVisibleChange="handleDropDownVisibleChange"初次选择下拉列表的时候执行,可以用于初始化数据
  • @popupScroll="handlePopupScroll"下拉列表滚动的时候执行的回调,用于判断是否加载到了底部
  • <v-nodes :vnodes="menu" />这个代表的就是那个下拉列表项数据,没有这个就不渲染

参考文章

https://blog.csdn.net/qq_36437172/article/details/109515201