| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <template>
- <list-view
- class="common-list"
- :scroll-y="true"
- @scrolltolower="handleLoadMore"
- :refresher-enabled="refresherEnabled"
- :refresher-triggered="refreshing"
- @refresherrefresh="handleRefresh"
- >
- <!-- 列表项 - 使用插槽自定义内容 -->
- <list-item
- v-for="(item, index) in dataList"
- :key="getItemKey(item, index)"
- class="common-list-item"
- @click="handleItemClick(item, index)"
- >
- <slot :item="item" :index="index"></slot>
- </list-item>
- <!-- 加载更多提示 -->
- <list-item class="load-more">
- <slot name="loadMore" :loading="loading" :hasMore="hasMore" :loadingText="loadingText">
- <text class="load-more-text">{{ loadingText }}</text>
- </slot>
- </list-item>
- </list-view>
- </template>
- <script setup lang="uts">
- import { computed } from 'vue'
- // Props 定义
- type Props = {
- // 数据列表
- dataList: any[]
- // 是否正在加载
- loading?: boolean
- // 是否正在刷新
- refreshing?: boolean
- // 是否还有更多数据
- hasMore?: boolean
- // 是否启用下拉刷新
- refresherEnabled?: boolean
- // 自定义加载提示文本
- customLoadingText?: string
- // 列表项的 key 字段名
- itemKey?: string
- }
- const props = withDefaults(defineProps<Props>(), {
- loading: false,
- refreshing: false,
- hasMore: true,
- refresherEnabled: true,
- customLoadingText: '',
- itemKey: 'id'
- })
- // 事件定义
- type Emits = {
- (e: 'refresh'): void
- (e: 'loadMore'): void
- (e: 'itemClick', item: any, index: number): void
- }
- const emit = defineEmits<Emits>()
- // 加载提示文本
- const loadingText = computed((): string => {
- if (props.customLoadingText.length > 0) {
- return props.customLoadingText
- }
- if (props.loading) {
- return '加载中...'
- }
- if (!props.hasMore) {
- return '没有更多数据了'
- }
- return '上拉加载更多'
- })
- // 获取列表项的 key
- const getItemKey = (item: any, index: number): string => {
- // 直接使用 index 作为 key,避免类型转换问题
- // 响应式对象无法安全转换为 UTSJSONObject
- return `item-${index}`
- }
- // 下拉刷新
- const handleRefresh = (): void => {
- emit('refresh')
- }
- // 加载更多
- const handleLoadMore = (): void => {
- if (!props.hasMore || props.loading) {
- return
- }
- emit('loadMore')
- }
- // 列表项点击
- const handleItemClick = (item: any, index: number): void => {
- emit('itemClick', item, index)
- }
- </script>
- <style lang="scss">
- .common-list {
- flex: 1;
- }
- .common-list-item {
- // 默认样式,具体样式由使用方通过插槽内容定义
- }
- .load-more {
- padding: 30rpx;
- justify-content: center;
- align-items: center;
- &-text {
- font-size: 26rpx;
- color: #999999;
- }
- }
- </style>
|