1.pc端分页+h5端加载更多钩子函数:
import { ref, onMounted, toRefs, watch } from 'vue'interface IremoteFn {remoteFn: (arg1: any) => Promise<any>emit: any
}
const useListPage = (props: any, { remoteFn, emit }: IremoteFn) => {const { list } = toRefs(props)interface IPaginationProp {pageNum: numberpageSize: numbertotal: string | number}const loadAll = ref(false)const loading = ref(false)const pagination = ref<IPaginationProp>({pageSize: 10,total: 0,pageNum: 1})const dataList = ref<any[]>([])// h5端上滑加载更多const loadMore = () => {if (loading.value) returnpagination.value.pageNum = pagination.value.pageNum + 1initData()}// 初始化数据(h5端下拉刷新)const onLoad = () => {pagination.value.pageNum = 1dataList.value = []initData()}// pc分页-改变pageNum回调const handleCurrentChange = (pageNum: number) => {pagination.value.pageNum = pageNumdataList.value = []initData()}// pc分页-pageSize回调const handleSizeChange = (pageSize: number) => {pagination.value.pageSize = pageSizepagination.value.pageNum = 1dataList.value = []initData()}// 调用分页接口const initData = () => {if (loading.value) {return}loading.value = trueemit('showLoading')remoteFn({pageNo: pagination.value.pageNum,pageSize: pagination.value.pageSize}).then((res) => {loading.value = falseconst { list = [], total } = resif (pagination.value.pageNum == 1) {dataList.value = list || []} else {dataList.value = dataList.value.concat(list)if(list.length < pagination.value.pageSize) {loadAll.value = true}}pagination.value.total = Number(total)if (dataList.value.length >= total) {loadAll.value = true}}).finally(() => {loading.value = falseemit('hideLoading')})}onMounted(() => {onLoad()})watch(() => list.value,() => {if (list.value) {dataList.value = list.value || []}},{deep: true,immediate: true})return {loadAll,loading,pagination,dataList,loadMore,onLoad,handleCurrentChange,handleSizeChange}
}export default useListPage
使用钩子:
const props = defineProps<{list?: any[]
}>()const { list } = toRefs(props)const emit = defineEmits(['showLoading', 'hideLoading'])
// 按需获取值和方法
const { handleSizeChange, handleCurrentChange, dataList, pagination } = useListPage(props, {emit,remoteFn: xxx方法
})
2.下拉刷新+上滑加载更多组件:
<template><van-pull-refresh v-model="refreshing" @refresh="onRefresh"><van-list v-model="loading" :finished="finished" :finished-text="finishedText" @load="loadMore"><slot name="content"></slot></van-list></van-pull-refresh>
</template><script lang="ts" setup>
import { ref, toRefs } from 'vue'
const props = defineProps<{finished: booleanfinishedText?: string
}>()
const { finished } = toRefs(props)
const emit = defineEmits(['fetchData', 'onLoad'])const loading = ref<boolean>(false)
const refreshing = ref<boolean>(false)async function loadMore() {if (loading.value) returnloading.value = truetry {await emit('fetchData')} finally {loading.value = false}
}async function onRefresh() {refreshing.value = trueawait emit('onLoad')refreshing.value = false
}
</script>
<style lang="less" scoped>
:deep(.van-list .van-list__finished-text) {font-size: 12px;line-height: 20px;margin-top: 8px;
}
</style>
3.h5页面使用:
<template><ListRefresh:finished="loadAll":finishedText="finishedText"@fetch-data="loadMore"@on-load="onLoad"><template #content><div class="list"><div class="list-box" v-if="dataList && dataList.length > 0"><div class="item" v-for="item in dataList" :key="item">{{ item.xxx }}</div></div><div v-else class="not-data">暂无数据</div><div v-if="!loadAll && dataList.length > 0" class="more-btn" @click="loadMore"><van-loading v-if="loading" size="14px" type="spinner">加载中</van-loading><span v-else>查看更多</span></div></div></template></ListRefresh>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { remoteFn } from '@/api'
import ListRefresh from '../ListRefresh.vue'
import useListPage from '../../hooks/useListPage'const props = defineProps<{list?: any[]
}>()const emit = defineEmits(['showLoading', 'hideLoading'])
const { loadAll, loading, dataList, loadMore, onLoad } = useListPage(props, {emit,remoteFn
})const finishedText = computed(() => {return loadAll.value && dataList.value.length > 0 ? '没有更多了' : ''
})
</script>
<style lang="less" scoped></style>
4.pc端使用:
<template><div class="content"><div class="c-table"><div class="c-thead"><div class="c-tr"><div class="c-td enroll-date">开始日期</div><div class="c-td graduate-date">结束日期</div></div></div><div class="c-tbody" v-if="dataList && dataList.length > 0"><div class="c-tr" v-for="item in dataList" :key="item"><div class="c-td">{{ item.startDate }}</div><div class="c-td">{{ item.endDate }}</div></div></div><div class="no-data" v-else>暂无数据</div></div><div class="buttom-box"><el-config-provider :locale="ZH_CH"><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pagination.pageNum":page-sizes="[10, 20, 50, 100]":page-size="pagination.pageSize":layout="'total, sizes, prev, pager, next, jumper'":total="pagination.total"></el-pagination></el-config-provider></div></div>
</template>
<script setup lang="ts" name="xxx">
import { ElPagination, ElConfigProvider } from 'element-plus'
import ZH_CH from 'element-plus/lib/locale/lang/zh-cn'
import { remoteFn} from '@/api'
import useListPage from './useListPage'const props = defineProps<{list?: any[]
}>()const emit = defineEmits(['showLoading', 'hideLoading'])
const { handleSizeChange, handleCurrentChange, dataList, pagination } = useListPage(props, {emit,remoteFn
})
</script>