6 changed files with 223 additions and 172 deletions
@ -1,147 +0,0 @@ |
|||
<script setup lang="ts"> |
|||
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'; |
|||
import { ref, reactive, toRefs, nextTick, onMounted } from 'vue' |
|||
|
|||
type argument = { |
|||
customListType?: 'default' | 'custom' | 'scroll' |
|||
isPerformSearch?: boolean |
|||
isPullDownRefresh?: boolean |
|||
onFormSearch: (formData: any, onSuccess: Function) => void |
|||
onRender?: Function |
|||
options?: { [n: string]: string | number | boolean } |
|||
emptyText?: string |
|||
emptyHeight?: number |
|||
} |
|||
|
|||
const props = withDefaults(defineProps<argument>(), { |
|||
customListType: 'default', |
|||
isPerformSearch: true, |
|||
isPullDownRefresh: true, |
|||
onFormSearch: () => { |
|||
console.log('onFormSearch') |
|||
}, |
|||
onRender: () => { |
|||
console.log('onRender') |
|||
}, |
|||
options: () => { |
|||
return {} |
|||
}, |
|||
emptyText: '暂无数据~', |
|||
emptyHeight: 60 |
|||
}) |
|||
|
|||
let { options, isPerformSearch, isPullDownRefresh, onFormSearch, onRender } = toRefs(props) |
|||
|
|||
const list = ref<any[]>([]) |
|||
const status = ref('loading') |
|||
const initing = ref(true) |
|||
const loading = ref(true) |
|||
const query = reactive({ |
|||
page: 1, |
|||
limit: 10, |
|||
total: 0 |
|||
}) |
|||
|
|||
const loadData = (callback?: Function) => { |
|||
uni.showLoading({ title: '数据加载中' }) |
|||
loading.value = true |
|||
const params = { ...query, ...options.value } as { [n: string]: string | number | boolean } |
|||
delete params.total |
|||
|
|||
setTimeout(() => { |
|||
onFormSearch.value(params, ({ data }: { data: { data: any; total: number } }) => { |
|||
loading.value = false |
|||
initing.value = false |
|||
callback && callback() |
|||
query.page = params.page as number |
|||
query.limit = params.limit as number |
|||
query.total = data.total || 0 |
|||
list.value = [...list.value, ...data.data] |
|||
|
|||
status.value = query.page * query.limit >= query.total ? 'nomore' : 'loading' |
|||
|
|||
onRender.value && onRender.value(data) |
|||
|
|||
uni.hideLoading() |
|||
}) |
|||
}, 100) |
|||
} |
|||
|
|||
const refreshFn = (callback?: Function) => { |
|||
query.page = 1 |
|||
query.total = 0 |
|||
list.value = [] |
|||
initing.value = true |
|||
loadData(callback) |
|||
} |
|||
|
|||
const onScrolltolower = () => { |
|||
if (query.page * query.limit >= query.total) { |
|||
status.value = 'nomore' |
|||
} else { |
|||
if (loading.value) return |
|||
|
|||
setTimeout(() => { |
|||
status.value = 'loading' |
|||
query.page += 1 |
|||
loadData() |
|||
}, 1000) |
|||
} |
|||
} |
|||
|
|||
onMounted(() => { |
|||
if (isPerformSearch.value) { |
|||
nextTick(() => { |
|||
refreshFn() |
|||
}) |
|||
} |
|||
}) |
|||
|
|||
onPullDownRefresh(() => { |
|||
if (isPullDownRefresh.value) refreshFn(() => uni.stopPullDownRefresh()) |
|||
}) |
|||
|
|||
onReachBottom(() => { |
|||
if (props.customListType !== 'scroll') { |
|||
onScrolltolower() |
|||
} |
|||
}) |
|||
|
|||
defineExpose({ |
|||
list, |
|||
refreshFn |
|||
}) |
|||
</script> |
|||
|
|||
<template> |
|||
<view v-if="!initing"> |
|||
<block v-if="list.length > 0"> |
|||
<template v-if="customListType === 'custom'"> |
|||
<slot v-bind:data="list" /> |
|||
<u-loadmore :status="status" /> |
|||
</template> |
|||
<template v-else-if="customListType === 'scroll'"> |
|||
<scroll-view class="scroll-view" scroll-y @scrolltolower="onScrolltolower"> |
|||
<view v-for="(item, index) in list" :key="index"> |
|||
<slot v-bind:row="item" v-bind:index="index" /> |
|||
</view> |
|||
<u-loadmore :status="status" /> |
|||
</scroll-view> |
|||
</template> |
|||
<template v-else> |
|||
<view v-for="(item, index) in list" :key="index"> |
|||
<slot v-bind:row="item" v-bind:index="index" /> |
|||
</view> |
|||
<u-loadmore :status="status" /> |
|||
</template> |
|||
</block> |
|||
<ex-empty v-show="list.length <= 0 && status === 'nomore'" :height="emptyHeight" :tips="emptyText" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped> |
|||
.scroll-view { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,181 @@ |
|||
@charset "UTF-8"; |
|||
#app { |
|||
box-sizing: border-box; |
|||
background-color: #f5f5f5; |
|||
} |
|||
|
|||
/* 颜色变量 */ |
|||
/*============================= 文字尺寸 =============================*/ |
|||
image { |
|||
width: 100%; |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
view { |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
/*============================= 弹性盒子 =============================*/ |
|||
.flex-end-evenly, .flex-end-around, .flex-end-between, .flex-end-end, .flex-end-center, .flex-end-start, .flex-center-evenly, .flex-center-around, .flex-center-between, .flex-center-end, .flex-center-start, .flex-start-evenly, .flex-start-around, .flex-start-between, .flex-start-end, .flex-start-center, .flex-start-start, .flex { |
|||
display: flex; |
|||
flex-wrap: nowrap; |
|||
} |
|||
|
|||
.flex { |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.flex-start-start { |
|||
align-items: flex-start; |
|||
justify-content: flex-start; |
|||
} |
|||
.flex-start-center { |
|||
align-items: flex-start; |
|||
justify-content: center; |
|||
} |
|||
.flex-start-end { |
|||
align-items: flex-start; |
|||
justify-content: flex-end; |
|||
} |
|||
.flex-start-between { |
|||
align-items: flex-start; |
|||
justify-content: space-between; |
|||
} |
|||
.flex-start-around { |
|||
align-items: flex-start; |
|||
justify-content: space-around; |
|||
} |
|||
.flex-start-evenly { |
|||
align-items: flex-start; |
|||
justify-content: space-evenly; |
|||
} |
|||
.flex-center-start { |
|||
align-items: center; |
|||
justify-content: flex-start; |
|||
} |
|||
.flex-center-end { |
|||
align-items: center; |
|||
justify-content: flex-end; |
|||
} |
|||
.flex-center-between { |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
} |
|||
.flex-center-around { |
|||
align-items: center; |
|||
justify-content: space-around; |
|||
} |
|||
.flex-center-evenly { |
|||
align-items: center; |
|||
justify-content: space-evenly; |
|||
} |
|||
.flex-end-start { |
|||
align-items: flex-end; |
|||
justify-content: flex-start; |
|||
} |
|||
.flex-end-center { |
|||
align-items: flex-end; |
|||
justify-content: center; |
|||
} |
|||
.flex-end-end { |
|||
align-items: flex-end; |
|||
justify-content: flex-end; |
|||
} |
|||
.flex-end-between { |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
} |
|||
.flex-end-around { |
|||
align-items: flex-end; |
|||
justify-content: space-around; |
|||
} |
|||
.flex-end-evenly { |
|||
align-items: flex-end; |
|||
justify-content: space-evenly; |
|||
} |
|||
|
|||
[class*=flex-].nowrap, |
|||
[class^=flex].nowrap { |
|||
flex-wrap: nowrap; |
|||
} |
|||
[class*=flex-].stretch, |
|||
[class^=flex].stretch { |
|||
align-items: stretch; |
|||
} |
|||
[class*=flex-].row, |
|||
[class^=flex].row { |
|||
flex-direction: row; |
|||
} |
|||
[class*=flex-].row-reverse, |
|||
[class^=flex].row-reverse { |
|||
flex-direction: "row-reverse"; |
|||
} |
|||
[class*=flex-].column, |
|||
[class^=flex].column { |
|||
flex-direction: column; |
|||
} |
|||
[class*=flex-].column-reverse, |
|||
[class^=flex].column-reverse { |
|||
flex-direction: "column-reverse"; |
|||
} |
|||
[class*=flex-].wrap, |
|||
[class^=flex].wrap { |
|||
flex-wrap: wrap; |
|||
} |
|||
[class*=flex-].wrap-reverse, |
|||
[class^=flex].wrap-reverse { |
|||
flex-wrap: "wrap-reverse"; |
|||
} |
|||
|
|||
.flex1 { |
|||
flex: 1; |
|||
} |
|||
|
|||
.flex2 { |
|||
flex: 2; |
|||
} |
|||
|
|||
.flex3 { |
|||
flex: 3; |
|||
} |
|||
|
|||
.flex4 { |
|||
flex: 4; |
|||
} |
|||
|
|||
/*============================= 文字溢出 =============================*/ |
|||
.text-ellipsis { |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
} |
|||
.text-ellipsis-2 { |
|||
overflow: hidden; |
|||
white-space: normal; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
line-clamp: 1; |
|||
-webkit-line-clamp: 2; |
|||
} |
|||
.text-ellipsis-3 { |
|||
overflow: hidden; |
|||
white-space: normal; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
line-clamp: 1; |
|||
-webkit-line-clamp: 3; |
|||
} |
|||
.text-ellipsis-4 { |
|||
overflow: hidden; |
|||
white-space: normal; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
line-clamp: 1; |
|||
-webkit-line-clamp: 4; |
|||
} |
|||
|
|||
/*# sourceMappingURL=uni.css.map */ |
|||
Loading…
Reference in new issue