zx-infinite-scroll 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +290 -10
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -84,34 +84,83 @@ app.mount('#app');
84
84
 
85
85
  | 属性 | 类型 | 默认值 | 说明 |
86
86
  |------|------|--------|------|
87
- | fetchFn | `(params: FetchParams) => Promise<FetchResult<T>>` | - | 数据请求函数(必填) |
88
- | params | `Record<string, any>` | `{}` | 查询参数,变化时自动重新加载 |
87
+ | fetchFn | `(params: FetchParams) => Promise<FetchResult<T>>` | - | 数据请求函数(必填),需返回 `{ records: T[], total: number }` |
88
+ | params | `Record<string, any>` | `{}` | 查询参数(如筛选条件),变化时自动重新加载 |
89
89
  | pageSize | `number` | `10` | 每页条数 |
90
90
  | autoReload | `boolean` | `true` | params 变化时是否自动重新加载 |
91
91
  | immediate | `boolean` | `true` | 是否在挂载时自动加载首页 |
92
92
  | pullRefresh | `boolean` | `false` | 是否启用下拉刷新 |
93
93
  | pullThreshold | `number` | `70` | 下拉刷新触发距离(px) |
94
- | loadThreshold | `number` | `50` | 上拉加载触发距离(px) |
94
+ | loadThreshold | `number` | `50` | 上拉加载触发距离(距离底部 px) |
95
+ | emptyText | `string` | `'暂无数据'` | 空状态文案 |
96
+ | pullingText | `string` | `'下拉刷新'` | 下拉中的文案 |
97
+ | loosingText | `string` | `'释放即可刷新'` | 释放刷新的文案 |
98
+ | refreshingText | `string` | `'加载中...'` | 刷新中的文案 |
99
+ | loadingText | `string` | `'加载中...'` | 加载中的文案 |
100
+ | finishedText | `string` | `'没有更多了~'` | 加载完成的文案 |
101
+ | errorText | `string` | `'加载失败,点击重试'` | 加载失败的文案 |
102
+
103
+ #### FetchParams 类型
104
+
105
+ ```typescript
106
+ interface FetchParams {
107
+ page: number; // 当前页码,从 1 开始
108
+ pageSize: number; // 每页条数
109
+ [key: string]: any; // 其他自定义参数(从 params prop 传入)
110
+ }
111
+ ```
112
+
113
+ #### FetchResult 类型
114
+
115
+ ```typescript
116
+ interface FetchResult<T> {
117
+ records: T[]; // 当前页数据列表
118
+ total: number; // 总条数
119
+ }
120
+ ```
95
121
 
96
122
  ### InfiniteScrollV2 Events
97
123
 
98
124
  | 事件 | 参数 | 说明 |
99
125
  |------|------|------|
100
- | success | `{ records: T[], total: number, reset: boolean }` | 加载成功 |
101
- | error | `err: unknown` | 加载失败 |
126
+ | success | `{ records: T[], total: number, reset: boolean }` | 加载成功时触发,每次成功(含分页)都会触发 |
127
+ | error | `err: unknown` | 加载失败时触发 |
128
+ | update:list | `list: T[]` | 列表内容变化时触发(支持 v-model:list) |
102
129
 
103
130
  ### InfiniteScrollV2 Slots
104
131
 
105
132
  | 插槽 | 参数 | 说明 |
106
133
  |------|------|------|
107
- | default | `{ list, loading, finished, isEmpty, error, total, reload }` | 列表内容 |
134
+ | default | `{ list, loading, finished, isEmpty, error, total, reload }` | 列表内容插槽 |
135
+
136
+ #### Slot 参数说明
137
+
138
+ ```typescript
139
+ {
140
+ list: T[]; // 当前列表数据
141
+ loading: boolean; // 是否正在加载
142
+ finished: boolean; // 是否已加载完所有数据
143
+ isEmpty: boolean; // 是否为空数据
144
+ error: boolean; // 是否加载失败
145
+ total: number; // 总条数
146
+ reload: () => void; // 重新加载第一页的方法
147
+ }
148
+ ```
108
149
 
109
150
  ### InfiniteScrollV2 Expose
110
151
 
111
- | 方法 | 说明 |
112
- |------|------|
113
- | reload() | 重新加载第一页 |
114
- | refresh() | 同 reload |
152
+ | 方法 | 类型 | 说明 |
153
+ |------|------|------|
154
+ | reload() | `() => Promise<void>` | 重新加载第一页 |
155
+ | refresh() | `() => Promise<void>` | 同 reload(别名) |
156
+ | list | `Ref<T[]>` | 当前列表数据(响应式) |
157
+ | loading | `Ref<boolean>` | 加载中状态(响应式) |
158
+ | finished | `Ref<boolean>` | 是否已加载完(响应式) |
159
+ | isEmpty | `Ref<boolean>` | 是否为空数据(响应式) |
160
+ | total | `Ref<number>` | 总条数(响应式) |
161
+ | finishLoad() | `() => void` | 完成上拉加载(透传 v1 方法) |
162
+ | finishRefresh() | `() => void` | 完成下拉刷新(透传 v1 方法) |
163
+ | checkContentHeight() | `() => void` | 检查内容高度(透传 v1 方法) |
115
164
 
116
165
  ## InfiniteScroll(基础组件)
117
166
 
@@ -151,6 +200,237 @@ const onRefresh = async () => {
151
200
  </template>
152
201
  ```
153
202
 
203
+ ### InfiniteScroll Props
204
+
205
+ | 属性 | 类型 | 默认值 | 说明 |
206
+ |------|------|--------|------|
207
+ | loading | `boolean` | `false` | 是否处于加载中状态 |
208
+ | finished | `boolean` | `false` | 是否已加载完所有数据 |
209
+ | isEmpty | `boolean` | `false` | 是否显示空状态 |
210
+ | emptyText | `string` | `'暂无数据'` | 空状态文案 |
211
+ | pullRefresh | `boolean` | `false` | 是否启用下拉刷新 |
212
+ | pullThreshold | `number` | `70` | 下拉刷新触发距离(px) |
213
+ | loadThreshold | `number` | `50` | 上拉加载触发距离(距离底部 px) |
214
+ | pullingText | `string` | `'下拉刷新'` | 下拉中的文案 |
215
+ | loosingText | `string` | `'释放即可刷新'` | 释放刷新的文案 |
216
+ | refreshingText | `string` | `'加载中...'` | 刷新中的文案 |
217
+ | loadingText | `string` | `'加载中...'` | 加载中的文案 |
218
+ | finishedText | `string` | `'没有更多了~'` | 加载完成的文案 |
219
+ | errorText | `string` | `'加载失败,点击重试'` | 加载失败的文案 |
220
+ | error | `boolean` | `false` | 是否显示错误状态 |
221
+ | contentLoading | `boolean` | `false` | 内容区域是否显示加载状态(用于下拉刷新时的遮罩) |
222
+
223
+ ### InfiniteScroll Events
224
+
225
+ | 事件 | 参数 | 说明 |
226
+ |------|------|------|
227
+ | load | - | 触发上拉加载时触发 |
228
+ | refresh | - | 触发下拉刷新时触发 |
229
+ | retry | - | 点击错误重试时触发 |
230
+
231
+ ### InfiniteScroll Expose
232
+
233
+ | 方法 | 类型 | 说明 |
234
+ |------|------|------|
235
+ | finishRefresh() | `() => void` | 完成下拉刷新,调用后收起刷新指示器 |
236
+ | finishPullDown() | `() => void` | 同 finishRefresh(别名) |
237
+ | finishLoad() | `() => void` | 完成上拉加载 |
238
+ | finishPullUp() | `() => void` | 同 finishLoad(别名) |
239
+ | checkContentHeight() | `() => void` | 检查内容高度,不足一屏时自动触发加载 |
240
+
241
+ ### InfiniteScroll Slots
242
+
243
+ | 插槽 | 说明 |
244
+ |------|------|
245
+ | default | 列表内容 |
246
+
247
+ ---
248
+
249
+ ## 完整使用示例
250
+
251
+ ### 示例 1:基础列表
252
+
253
+ ```vue
254
+ <script setup lang="ts">
255
+ import { InfiniteScrollV2 } from 'zx-infinite-scroll';
256
+ import 'zx-infinite-scroll/dist/style.css';
257
+
258
+ interface Item {
259
+ id: number;
260
+ name: string;
261
+ }
262
+
263
+ const fetchData = async ({ page, pageSize }) => {
264
+ const res = await fetch(`/api/list?page=${page}&pageSize=${pageSize}`);
265
+ const data = await res.json();
266
+ return {
267
+ records: data.list,
268
+ total: data.total
269
+ };
270
+ };
271
+ </script>
272
+
273
+ <template>
274
+ <InfiniteScrollV2 :fetch-fn="fetchData">
275
+ <template #default="{ list }">
276
+ <div v-for="item in list" :key="item.id" class="item">
277
+ {{ item.name }}
278
+ </div>
279
+ </template>
280
+ </InfiniteScrollV2>
281
+ </template>
282
+ ```
283
+
284
+ ### 示例 2:带下拉刷新和筛选参数
285
+
286
+ ```vue
287
+ <script setup lang="ts">
288
+ import { ref } from 'vue';
289
+ import { InfiniteScrollV2 } from 'zx-infinite-scroll';
290
+ import 'zx-infinite-scroll/dist/style.css';
291
+
292
+ const keyword = ref('');
293
+ const category = ref('');
294
+
295
+ const fetchData = async ({ page, pageSize, keyword, category }) => {
296
+ const res = await fetch(
297
+ `/api/list?page=${page}&pageSize=${pageSize}&keyword=${keyword}&category=${category}`
298
+ );
299
+ return await res.json();
300
+ };
301
+ </script>
302
+
303
+ <template>
304
+ <input v-model="keyword" placeholder="搜索关键词" />
305
+ <select v-model="category">
306
+ <option value="">全部分类</option>
307
+ <option value="1">分类1</option>
308
+ <option value="2">分类2</option>
309
+ </select>
310
+
311
+ <InfiniteScrollV2
312
+ :fetch-fn="fetchData"
313
+ :params="{ keyword, category }"
314
+ :pull-refresh="true"
315
+ :page-size="20"
316
+ >
317
+ <template #default="{ list, loading, reload }">
318
+ <div v-for="item in list" :key="item.id" class="item">
319
+ {{ item.name }}
320
+ </div>
321
+ <button v-if="!loading" @click="reload">手动刷新</button>
322
+ </template>
323
+ </InfiniteScrollV2>
324
+ </template>
325
+ ```
326
+
327
+ ### 示例 3:监听事件
328
+
329
+ ```vue
330
+ <script setup lang="ts">
331
+ import { InfiniteScrollV2 } from 'zx-infinite-scroll';
332
+ import 'zx-infinite-scroll/dist/style.css';
333
+
334
+ const handleSuccess = ({ records, total, reset }) => {
335
+ console.log('加载成功', { records, total, reset });
336
+ };
337
+
338
+ const handleError = (err) => {
339
+ console.error('加载失败', err);
340
+ };
341
+
342
+ const fetchData = async ({ page, pageSize }) => {
343
+ // 模拟可能失败的请求
344
+ const res = await fetch(`/api/list?page=${page}&pageSize=${pageSize}`);
345
+ if (!res.ok) throw new Error('请求失败');
346
+ return await res.json();
347
+ };
348
+ </script>
349
+
350
+ <template>
351
+ <InfiniteScrollV2
352
+ :fetch-fn="fetchData"
353
+ @success="handleSuccess"
354
+ @error="handleError"
355
+ >
356
+ <template #default="{ list }">
357
+ <div v-for="item in list" :key="item.id">
358
+ {{ item.name }}
359
+ </div>
360
+ </template>
361
+ </InfiniteScrollV2>
362
+ </template>
363
+ ```
364
+
365
+ ### 示例 4:使用基础组件(手动控制)
366
+
367
+ ```vue
368
+ <script setup lang="ts">
369
+ import { ref } from 'vue';
370
+ import { InfiniteScroll } from 'zx-infinite-scroll';
371
+ import 'zx-infinite-scroll/dist/style.css';
372
+
373
+ const scrollRef = ref();
374
+ const list = ref([]);
375
+ const loading = ref(false);
376
+ const finished = ref(false);
377
+ const error = ref(false);
378
+ const page = ref(1);
379
+ const total = ref(0);
380
+
381
+ const loadData = async () => {
382
+ loading.value = true;
383
+ error.value = false;
384
+ try {
385
+ const res = await fetch(`/api/list?page=${page.value}&pageSize=10`);
386
+ const data = await res.json();
387
+ list.value.push(...data.records);
388
+ total.value = data.total;
389
+ finished.value = list.value.length >= total.value;
390
+ page.value++;
391
+ } catch (err) {
392
+ error.value = true;
393
+ } finally {
394
+ loading.value = false;
395
+ scrollRef.value?.finishLoad();
396
+ }
397
+ };
398
+
399
+ const refreshData = async () => {
400
+ page.value = 1;
401
+ list.value = [];
402
+ finished.value = false;
403
+ await loadData();
404
+ scrollRef.value?.finishRefresh();
405
+ };
406
+
407
+ const retryLoad = () => {
408
+ if (list.value.length === 0) {
409
+ refreshData();
410
+ } else {
411
+ loadData();
412
+ }
413
+ };
414
+ </script>
415
+
416
+ <template>
417
+ <InfiniteScroll
418
+ ref="scrollRef"
419
+ :loading="loading"
420
+ :finished="finished"
421
+ :error="error"
422
+ :pull-refresh="true"
423
+ @load="loadData"
424
+ @refresh="refreshData"
425
+ @retry="retryLoad"
426
+ >
427
+ <div v-for="item in list" :key="item.id" class="item">
428
+ {{ item.name }}
429
+ </div>
430
+ </InfiniteScroll>
431
+ </template>
432
+ ```
433
+
154
434
  ## License
155
435
 
156
436
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zx-infinite-scroll",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Vue 3 infinite scroll component with pull-to-refresh support",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.es.js",