zx-infinite-scroll 1.0.0 → 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 +298 -15
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @zhixin/infinite-scroll
1
+ # zx-infinite-scroll
2
2
 
3
3
  Vue 3 无限滚动组件,支持下拉刷新、上拉加载。
4
4
 
@@ -15,7 +15,7 @@ Vue 3 无限滚动组件,支持下拉刷新、上拉加载。
15
15
  ## 安装
16
16
 
17
17
  ```bash
18
- npm install @zhixin/infinite-scroll
18
+ npm install zx-infinite-scroll
19
19
  ```
20
20
 
21
21
  ## 使用
@@ -24,7 +24,8 @@ npm install @zhixin/infinite-scroll
24
24
 
25
25
  ```vue
26
26
  <script setup lang="ts">
27
- import { InfiniteScrollV2 } from '@zhixin/infinite-scroll';
27
+ import { InfiniteScrollV2 } from 'zx-infinite-scroll';
28
+ import 'zx-infinite-scroll/dist/style.css';
28
29
 
29
30
  interface Item {
30
31
  id: number;
@@ -60,7 +61,8 @@ const fetchData = async ({ page, pageSize }) => {
60
61
 
61
62
  ```ts
62
63
  import { createApp } from 'vue';
63
- import InfiniteScrollPlugin from '@zhixin/infinite-scroll';
64
+ import InfiniteScrollPlugin from 'zx-infinite-scroll';
65
+ import 'zx-infinite-scroll/dist/style.css';
64
66
  import App from './App.vue';
65
67
 
66
68
  const app = createApp(App);
@@ -82,34 +84,83 @@ app.mount('#app');
82
84
 
83
85
  | 属性 | 类型 | 默认值 | 说明 |
84
86
  |------|------|--------|------|
85
- | fetchFn | `(params: FetchParams) => Promise<FetchResult<T>>` | - | 数据请求函数(必填) |
86
- | params | `Record<string, any>` | `{}` | 查询参数,变化时自动重新加载 |
87
+ | fetchFn | `(params: FetchParams) => Promise<FetchResult<T>>` | - | 数据请求函数(必填),需返回 `{ records: T[], total: number }` |
88
+ | params | `Record<string, any>` | `{}` | 查询参数(如筛选条件),变化时自动重新加载 |
87
89
  | pageSize | `number` | `10` | 每页条数 |
88
90
  | autoReload | `boolean` | `true` | params 变化时是否自动重新加载 |
89
91
  | immediate | `boolean` | `true` | 是否在挂载时自动加载首页 |
90
92
  | pullRefresh | `boolean` | `false` | 是否启用下拉刷新 |
91
93
  | pullThreshold | `number` | `70` | 下拉刷新触发距离(px) |
92
- | 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
+ ```
93
121
 
94
122
  ### InfiniteScrollV2 Events
95
123
 
96
124
  | 事件 | 参数 | 说明 |
97
125
  |------|------|------|
98
- | success | `{ records: T[], total: number, reset: boolean }` | 加载成功 |
99
- | error | `err: unknown` | 加载失败 |
126
+ | success | `{ records: T[], total: number, reset: boolean }` | 加载成功时触发,每次成功(含分页)都会触发 |
127
+ | error | `err: unknown` | 加载失败时触发 |
128
+ | update:list | `list: T[]` | 列表内容变化时触发(支持 v-model:list) |
100
129
 
101
130
  ### InfiniteScrollV2 Slots
102
131
 
103
132
  | 插槽 | 参数 | 说明 |
104
133
  |------|------|------|
105
- | 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
+ ```
106
149
 
107
150
  ### InfiniteScrollV2 Expose
108
151
 
109
- | 方法 | 说明 |
110
- |------|------|
111
- | reload() | 重新加载第一页 |
112
- | 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 方法) |
113
164
 
114
165
  ## InfiniteScroll(基础组件)
115
166
 
@@ -118,7 +169,8 @@ app.mount('#app');
118
169
  ```vue
119
170
  <script setup lang="ts">
120
171
  import { ref } from 'vue';
121
- import { InfiniteScroll } from '@zhixin/infinite-scroll';
172
+ import { InfiniteScroll } from 'zx-infinite-scroll';
173
+ import 'zx-infinite-scroll/dist/style.css';
122
174
 
123
175
  const list = ref([]);
124
176
  const loading = ref(false);
@@ -148,6 +200,237 @@ const onRefresh = async () => {
148
200
  </template>
149
201
  ```
150
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
+
151
434
  ## License
152
435
 
153
436
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zx-infinite-scroll",
3
- "version": "1.0.0",
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",