基于vant4+vue3封装list列表组件,下拉刷新上拉加载空状态显示、取消请求

2 篇文章 0 订阅
文章展示了如何在Vue应用中使用自定义组件PullRefreshList,该组件结合van-pull-refresh和van-list实现下拉刷新和上拉加载功能。通过props传递请求API、参数以及数据处理方法,子组件负责数据的加载和状态管理,父组件可以定制化加载文本、错误处理等。
摘要由CSDN通过智能技术生成

父组件使用

<template>
     <PullRefreshList ref="PullRefreshListRef" :requestApi="requestApi" :requestParams="requestParams">
        <template v-slot="{ data }">
            // 列表内容
            // <ListContent :data="data"></ListContent>
        </template>
     </PullRefreshList>
</template>

<script setup>
import { ref, computed, reactive } from "vue"
import PullRefreshList from '@/components/PullRefreshList.vue'
import ListContent from './components/ListContent.vue'
import axios from "axios"

// 列表请求
const PullRefreshListRef = ref(null)
const requestApi = (params) => {
    const { pageParams, requestParams,cancelToken } = params
    return axios({ url: "请求url", method: "GET", params: { ...pageParams, ...requestParams }, cancelToken })
}

// 请求参数
const requestParams = computed(() => {
    return {}
})

</script>

子组件   PullRefreshList.vue

<template>
    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
        <van-list v-model:loading="loading" v-model:error="error" :finished="finished" @load="onLoad"
            :offset="props.offsetList" :loading-text="props.loadingTextList" :finished-text="props.finishedTextList"
            :error-text="props.errorTextList" :immediate-check="props.immediateCheckList" :disabled="props.disabledList"
            :direction="props.directionList">
            <template v-for="item in listData" v-if="listData.length > 0">
                <slot :data="item"></slot>
            </template>
            <van-empty description="暂无数据" v-else />
        </van-list>
    </van-pull-refresh>
</template>

<script setup>
import { ref, reactive, watch } from 'vue';
import axios from "axios"
import { debounce } from "@/utils";
const props = defineProps({
    requestApi: Function, // 请求数据api
    requestError: Function, // 请求错误处理
    dataCallBack: Function, // 返回数据的回调函数,可以对数据进行处理
    requestParams: {
        type: Object,
        default: {}
    },  // 请求参数
    offsetList: {
        type: Number || String,
        default: 0
    },	// 滚动条与底部距离小于 offset 时触发 load 事件	number | string	300
    loadingTextList: {
        type: String,
        default: '加载中...'
    },	//加载过程中的提示文案	string	加载中...
    finishedTextList: {
        type: String,
        default: '加载完成,暂无更多'
    },	//加载完成后的提示文案	string	-
    errorTextList: {
        type: String,
        default: '获取失败,点击重新获取'
    },	//加载失败后的提示文案	string	-
    immediateCheckList: {
        type: Boolean,
        default: true
    },	//是否在初始化时立即执行滚动位置检查	boolean	true
    disabledList: {
        type: Boolean,
        default: false
    },  //是否禁用滚动加载	boolean	false
    directionList: {
        type: String,
        default: 'down'
    },  //滚动触发加载的方向,可选值为 up
})
// 下拉刷新是否处于加载中状态
const refreshing = ref(false)
// 上拉加载是否处于加载中状态
const loading = ref(false)
// 上拉加载失败
const error = ref(false)
// 是否已加载完成,加载完成后不再触发 load 事件
const finished = ref(false)
const pageParams = reactive({
    current: 1, // 当前页
    size: 10, // 每页数据条数
    total: 0, // 总页数
})
// 列表数据
const listData = ref([])
// 下拉刷新
const onRefresh = () => {
    handleReset();
    requestData(1)

}
// 上拉加载
const onLoad = () => {
    if (error.value) return
    requestData(2)
}
// 关闭加载状态
const loadStatus = (boolean) => {
    refreshing.value = boolean
    loading.value = boolean
}


// 初始化
const handleReset = () => {
    pageParams.current = 1
    finished.value = false
    error.value = false
}


// 监听请求参数是否发生变化
watch(() => props.requestParams, () => {
    onRefresh()
})

// 当前是否在请求中
const isRequest = ref(false)
let cancelFn = () => { }

/*
 *@functionName: requestData
 *@params1: type    1 下拉刷新   2 上拉加载
 *@description:  加载列表数据
*/
const requestData = (type, params = {}) => {
    if (!props.requestApi) {
        throw '请传入requestApi'
    }

    // 取消上次请求
    if (isRequest.value) {
        cancelFn();
    }
    loadStatus(true)
    debounceSendRequest(type, params)
}

const sendRequest = async (type, params) => {
    try {
        isRequest.value = true
        const { data } = await props.requestApi({
            pageParams: pageParams,
            requestParams: { ...props.requestParams, ...params },
            cancelToken: new axios.CancelToken(callBack => {
                cancelFn = callBack
            })
        })
        isRequest.value = false
        let requestData = data.data
        loadStatus(false)
        props.dataCallBack && (requestData = props.dataCallBack(requestData))
        if (requestData.records.length < pageParams.size) {
            finished.value = true
        }
        if (type === 1) {
            listData.value = requestData.records
        } else {
            listData.value = listData.value.concat(requestData.records)
        }
        pageParams.current++
        pageParams.size = requestData.size || pageParams.size
        pageParams.total = requestData.total || pageParams.total
    } catch (err) {
        isRequest.value = false
        if (err.code === "ERR_CANCELED") {
            return
        }
        if (type === 2) {
            error.value = true
        }
        loadStatus(false)
        props.requestError && props.requestError(err);
    }
}
let debounceSendRequest = debounce(sendRequest, 300)

const reLoad = (params) => {
    handleReset();
    requestData(1, params)
}

defineExpose({
    onRefresh,
    reLoad
})
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值