场景
uni-app 加载页面列表
如上图,如果不使用hooks,将重复写相同逻辑的代码
使用之后,代码量大大节省
hooks代码
// usePageList.ts
import { ref, type Ref } from 'vue'
interface ListOptionsRes<T> {
content: T[]
first: boolean
last: true
size: boolean
totalElements: number
totalPages: number
}
interface ListServiceParams {
page: number
size: number
}
type ListService<R> = (params: ListServiceParams) => Promise<ResOptions<ListOptionsRes<R>>>
interface Options {
page?: number
size?: number
}
type Status = 'more' | 'loading' | 'nomore'
export function usePageList<T>(service: ListService<T>, options: Options = {}) {
const page = ref(options.page ?? 1)
const size = ref(options.size ?? 10)
const loading = ref(false)
const status = ref<Status>('more')
const total = ref(0)
const list: Ref<T[]> = ref([])
const getList = async () => {
try {
status.value = 'loading'
const res = await service({ page: page.value, size: size.value })
if (list.value.length < res.data.totalElements) {
list.value.push(...res.data.content)
}
status.value = list.value.length >= res.data.totalElements ? 'nomore' : 'more'
page.value = list.value.length >= res.data.totalElements ? page.value : page.value + 1
} catch (error) {
status.value = 'more'
}
}
const search = () => {
list.value = []
page.value = options.page ?? 1
getList()
}
return {
page,
size,
loading,
status,
total,
list,
getList,
search
}
}
使用
<template>
<view class="page">
<view class="list">
<provider-item v-for="item in providerList" :key="item.id" :data="item"></provider-item>
<load-more :status="status"></load-more>
</view>
</view>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue'
import { getWindProviderList, type WindProviderItem } from '@/apis'
import { onReachBottom } from '@dcloudio/uni-app'
import { usePageList } from '@/hooks'
const form = reactive({ industry: '', area: [] as string[], company: '' })
const {
list: providerList,
status,
getList
} = usePageList<WindProviderItem>((params) => getWindProviderList({ ...params, ...form }))
getList()
// 下拉加载触发
onReachBottom(() => {
getList()
})
</script>