|
@@ -0,0 +1,135 @@
|
|
|
|
+<template>
|
|
|
|
+ <!-- 无限滚动区域 -->
|
|
|
|
+ <scroll-view class="scroll-container" :scroll-y="true" :refresher-enabled="true" :refresher-triggered="triggered"
|
|
|
|
+ :refresher-threshold="100" refresher-background="#F3F3F4" @refresherrefresh="onRefresh"
|
|
|
|
+ @scrolltolower="onReachBottom" @refresherrestore="onRestore">
|
|
|
|
+ <slot :list="list"></slot>
|
|
|
|
+ <uni-load-more :status="status" :contentText="contentText"></uni-load-more>
|
|
|
|
+ </scroll-view>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+ import {
|
|
|
|
+ ref,
|
|
|
|
+ onMounted,
|
|
|
|
+ computed,
|
|
|
|
+ reactive,
|
|
|
|
+ } from "vue";
|
|
|
|
+
|
|
|
|
+ import {
|
|
|
|
+ onLoad
|
|
|
|
+ } from "@dcloudio/uni-app"
|
|
|
|
+
|
|
|
|
+ const props = defineProps({
|
|
|
|
+ refreshFn: {
|
|
|
|
+ type: Function,
|
|
|
|
+ required: true
|
|
|
|
+ },
|
|
|
|
+ size: {
|
|
|
|
+ type: Number,
|
|
|
|
+ default: 5
|
|
|
|
+ },
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const page = ref(1);
|
|
|
|
+ const list = ref([]); // 项目列表
|
|
|
|
+ const triggered = ref(false); // 是否触发下拉刷新
|
|
|
|
+ const freshing = ref(false); // 是否加载中
|
|
|
|
+ const total = ref(0); // 项目总数
|
|
|
|
+ const status = ref('more');
|
|
|
|
+ const contentText = {
|
|
|
|
+ contentdown: '查看更多',
|
|
|
|
+ contentrefresh: '加载中',
|
|
|
|
+ contentnomore: '没有更多'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 是否已完全加载
|
|
|
|
+ */
|
|
|
|
+ const isComplete = computed(() => {
|
|
|
|
+ if (total.value === 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return total.value === list.value.length
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 重置
|
|
|
|
+ function reset() {
|
|
|
|
+ list.value = [];
|
|
|
|
+ page.value = 1;
|
|
|
|
+ triggered.value = false;
|
|
|
|
+ freshing.value = false;
|
|
|
|
+ total.value = 0;
|
|
|
|
+ status.value = 'more';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ onLoad(() => {
|
|
|
|
+ freshing.value = false;
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ triggered.value = true
|
|
|
|
+ }, 50)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 获取数据
|
|
|
|
+ function getData(action) {
|
|
|
|
+ const options = Object.assign({}, {
|
|
|
|
+ page: page.value,
|
|
|
|
+ size: props.size,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 补充参数
|
|
|
|
+ if (props.otherOption) {
|
|
|
|
+ options = Object.assign({}, options, props.otherOption);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ props.refreshFn(options).then(res => {
|
|
|
|
+ total.value = res.data.total;
|
|
|
|
+ action === "do-search" && (list.value = res.data.data); // 查询更新
|
|
|
|
+ action === "pull-down-refresh" && (list.value = res.data.data); // 下拉更新数据
|
|
|
|
+ action === "reach-buttom" && (list.value = [...list.value, ...res.data.data]); // 无限滚动更新数据
|
|
|
|
+ }).finally(() => {
|
|
|
|
+ triggered.value = false;
|
|
|
|
+ freshing.value = false;
|
|
|
|
+ if (total.value !== list.value.length) {
|
|
|
|
+ status.value = 'more';
|
|
|
|
+ } else {
|
|
|
|
+ status.value = 'noMore';
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 下拉刷新触发
|
|
|
|
+ function onRefresh() {
|
|
|
|
+ if (freshing.value) return;
|
|
|
|
+ status.value = 'loading';
|
|
|
|
+ freshing.value = true;
|
|
|
|
+ triggered.value = true;
|
|
|
|
+ page.value = 1;
|
|
|
|
+ getData('pull-down-refresh');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 下拉刷新复位
|
|
|
|
+ function onRestore() {
|
|
|
|
+ triggered.value = 'restore'; // 需要重置
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 无限滚动
|
|
|
|
+ function onReachBottom() {
|
|
|
|
+ if (freshing.value) return;
|
|
|
|
+ if (isComplete.value) return;
|
|
|
|
+ freshing.value = true;
|
|
|
|
+ page.value++;
|
|
|
|
+ getData('reach-buttom')
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ defineExpose({
|
|
|
|
+ onRefresh
|
|
|
|
+ })
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style>
|
|
|
|
+
|
|
|
|
+</style>
|