【山竹记账前端-react】14.无限加载列表
大纲链接 §
[toc]
1. 无限加载的实现思路 ⇧
- 访问
/items页面,请求/items?page=1 - 每次加载10项数据,返回
{ resources: [], pager: {count: 10, per_page: 10, page: 1, }, } - 点击加载更多时,在原先数据后再插入10项数据
?page=2 - 页码乘以每页项目数,和总条目数对比,判断是否有更多数据加载
- 使用
hasMore = (page - 1) * per_page + resourses.length < count计算 是否还有更多数据 - 报错和特殊情况情况
- 加载第一页:
resources返回空数组,则显示暂无数据; - 请求第一页时,出错了,添加错误提示
- 请求第二页时,出错了,添加错误提示…
- 加载第一页:
- 显示正在加载状态,改变“加载更多”的文案为“正在加载”;成功后变为“没有更多”或者“加载更多”
2. useSWRInfinite ⇧
@/modules/items/ItemsSummary.tsx
|
|
- 使用
useSWRInfinite的数据模型,每次获取一页数据,向data中添加一份当前页的数据data = [{resources: [], pager: {}}, {resources: [], pager: {}}, {resources, pager}, ...]data会保留第一页以及后几页请求过的所有数据- 只需要遍历这个data就可以把每一页的数据都合并展示出来
pageIndex说明下标是从0开始的;否则应该是page- 仍使用
/api/v1/items模拟数据接口 fetcher函数中参数路径path时动态获取的,根据每次页码改而不同变
原先的
@/mock/mock.ts数据暂时为空,之后对它做一些高级的改造
|
|
3. 优化Mock,改造Mock数据 ⇧
实现 Mock 数据 模块化、自动生成假数据
重构 @/mock/mock.ts 模块化 ⇧
拆分为
@/mock/me.mock.ts和@/mock/items.mock.ts将其他相关数据剪切过去
|
|
|
|
@/mock/mock.ts
|
|
此时遇到
vite-plugin-mock插件bug,改用vite-plugin-mock-dev-server
改用 vite-plugin-mock-dev-server ⇧
vite-plugin-mock插件停止维护了,需要改用积极维护的且功能更多的vite-plugin-mock-dev-server
- 安装
pnpm add -D vite-plugin-mock-dev-server 卸载
pnpm remove vite-plugin-mock1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54import { fileURLToPath, URL } from 'node:url' import { defineConfig, UserConfigExport, ConfigEnv } from 'vite' import react from '@vitejs/plugin-react' import UnoCSS from 'unocss/vite' import jsxScoped from '@10coding/vite-plugin-jsx-scoped' import { consoleBanner } from "vite-plugin-console-banner" import { svgsprites } from './src/plugins/svgsprites.ts' import { noOptimizeIconList } from './src/plugins/noOptimizeIconList.ts' import { mockDevServerPlugin } from 'vite-plugin-mock-dev-server' export default defineConfig(({ command }: ConfigEnv) => ({ define: { __IS_DEV__: command === 'serve', }, plugins: [ UnoCSS(), jsxScoped({ scopedIdAttributeName: 'scopedid' }), mockDevServerPlugin({ dir: './src/mock', enabled: command === 'serve', reload: true, awaitInitialLoad: command === 'serve', exclude: [ '**/*.d.{js,ts,cjs,mjs,json,json5}', ], }), react(), consoleBanner({ text: "xmasuhai.xyz", font: "big", // 大小写不敏感,也可用 "Big"、"ANSI Shadow" color: "#476EE3", badges: [ { label: "徐帅的博客", url: "https://xmasuhai.xyz" }, { label: "徐帅${year}简历", url: "https://xmasuhai.xyz/my-latest-resume/" }, ], }), svgsprites({ noOptimizeList: noOptimizeIconList, }), ], server: { host: true, proxy: { '^/api': { target: '//192.168.0.104', }, }, }, resolve: { // 开启 Vite 8 的原生 tsconfig 路径解析支持 tsconfigPaths: true, alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), } } })) satisfies UserConfigExport原来的
mock.ts文件可以整个删除现在可以使用天然分模块的
@/mock/me.mock.ts和@/mock/items.mock.ts模拟数据文件
@/mock/me.mock.ts
|
|
@/mock/items.mock.ts
|
|
使用方式不变
1 2 3 4 5 6const getKey = (pageIndex: number = 0) => `/api/v1/items?page=${pageIndex + 1}` const { data, error, /* isLoading, isValidating, mutate, size, setSize */ } = useSWRInfinite( getKey, async (path) => (await request.get<Resources<Item[]>>(path)).data, )
4. 请求所有分页 ⇧
``
|
|
5. 没有更多数据 ⇧
``
|
|
6. 展示error ⇧
``
|
|
7. 展示loading ⇧
``
|
|
8. 为什么SWR有多余请求 ⇧
``
|
|
·未完待续·
参考文章
- 初始代码:https://github.com/FrankFang/zmvkoJ6n
- 提交历史(六次提交):https://github.com/FrankFang/FQz1DIhl/commits/master
- 最终代码:https://github.com/FrankFang/FQz1DIhl
相关文章
- Pagination
- 分页
- useSWRInfinite
- vite Mock-Dev-Server
- github vite-plugin-mock-dev-server
- npm vite-plugin-mock-dev-server
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名