UNPKG

rerumaccusamus

Version:

The meta-framework suite designed from scratch for frontend-focused modern web development.

206 lines (158 loc) 5.59 kB
--- title: 从 BFF 获取数据 --- 上一小节中,我们创建了【 函数写法 】的 BFF,这一小节中,我们将用该模式为联系人列表实现一个数据接口。 我们首先把不需要的样板文件清理掉,把 `index.ts` 重命名为 `contacts.ts`,执行以下命令: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; <Tabs> <TabItem value="macOS" label="macOS" default> ```bash rm -r api/info api/_app.ts mv api/index.ts api/contacts.ts ``` </TabItem> <TabItem value="Windows" label="Windows"> ```powershell rm -r api/info rm api/_app.ts mv api/index.ts api/contacts.ts ``` </TabItem> </Tabs> 此时 API 路由将变为 `/api/contacts`。 我们使用 [faker](https://github.com/Marak/Faker.js) 来 mock 需要的数据,首先安装依赖: ```bash pnpm add faker ````api/contacts.ts` 内容改为: ```js import { name, internet } from 'faker'; export const get = async () => { const mockData = new Array(20).fill(0).map(() => { const firstName = name.firstName(); return { name: firstName, avatar: `https://avatars.dicebear.com/api/identicon/${firstName}.svg`, email: internet.email(), }; }); return { code: 200, data: mockData }; }; ``` :::note 注 数据同样可以从远端接口获取,此处仅为了演示。 ::: 执行 `pnpm run dev`,访问 `http://localhost:8080/api/contacts`: ![browser-result](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/08/api-result.png) 接下来我们把 `src/contacts/App.tsx` 里硬编码的 `mockData` 改成从 BFF 加载。 我们将业务逻辑迁移到组件中,`App.tsx` 只保留简单的路由部分,执行: <Tabs> <TabItem value="macOS" label="macOS" default> ```bash mkdir -p src/contacts/components/AllContacts/ mkdir -p src/contacts/components/ArchivedContacts/ touch src/contacts/components/AllContacts/index.tsx touch src/contacts/components/ArchivedContacts/index.tsx ``` </TabItem> <TabItem value="Windows" label="Windows"> ```powershell mkdir -p src/contacts/components/AllContacts/ mkdir -p src/contacts/components/ArchivedContacts/ ni src/contacts/components/AllContacts/index.tsx ni src/contacts/components/ArchivedContacts/index.tsx ``` </TabItem> </Tabs> `ArchivedContacts/index.tsx` 的内容: ```js import { List } from 'antd'; import Item from '../Item'; const getAvatar = (users: Array<{ name: string; email: string }>) => users.map(user => ({ ...user, avatar: `https://avatars.dicebear.com/v2/identicon/${user.name}.svg`, })); const mockArchivedData = getAvatar([ { name: 'Thomas', email: 'w.kccip@bllmfbgv.dm' }, { name: 'Chow', email: 'f.lfqljnlk@ywoefljhc.af' }, ]); const ArchivedContacts = () => ( <List dataSource={mockArchivedData} renderItem={info => <Item key={info.name} info={info} />} /> ); export default ArchivedContacts; ``` `AllContacts/index.tsx` 的内容: ```tsx import { useState, useEffect } from 'react'; import { List } from 'antd'; import { get as concats } from '@api/contacts'; import Item from '../Item'; const AllContacts = () => { const [list, setList] = useState( [] as Array<{ name: string; email: string; avatar: string }>, ); const loadMockData = async () => { const { data } = await concats(); setList(data); }; useEffect(() => { if (!list.length) { loadMockData(); } }); return ( (list.length && ( <List dataSource={list} renderItem={info => <Item key={info.name} info={info} />} /> )) || ( <div className="p-4 items-center border-gray-200 border-b border-t custom-text-gray"> Pending... </div> ) ); }; export default AllContacts; ``` 在 Modern.js 中,可以通过调用函数(前后端一体化)的方式,直接调用 BFF 接口,调用时无需关心域名、路径等。 :::note 注 在使用 `pnpm run new` 创建 BFF 时,Modern.js 已经默认在 `tsconig.json` 中注入了别名。这也是之前提到的,生成器在项目创建之后并不会被抛弃,仍旧可以在开发过程中不断为项目提供新的内容。 ::: 接下来修改 `src/contacts/App.tsx`,把 `List` 组件的调用代码替换成上面的 `AllContacts` 和 `ArchivedContacts`: ```tsx <Route path="/" exact={true}> <Helmet> <title>All</title> </Helmet> <AllContacts /> </Route> <Route path="/archives" exact={true}> <Helmet> <title>Archives</title> </Helmet> <ArchivedContacts /> </Route> ``` 删除 `App.tsx` 里的 mock 数据和 `List` 组件,把 `Item` 组件替换成 `ContactList`: ```tsx import { useState } from 'react'; import { Radio, RadioChangeEvent } from 'antd'; import { Route, Switch, useHistory } from '@modern-js/runtime/router'; import { Helmet } from '@modern-js/runtime/head'; import 'tailwindcss/base.css'; import 'tailwindcss/components.css'; import 'tailwindcss/utilities.css'; import './styles/utils.css'; import AllContacts from './components/AllContacts'; import ArchivedContacts from './components/ArchivedContacts'; ``` 执行 `pnpm run dev`,再打开页面`http://localhost:8000/contacts`,可以看到页面加载后,会先初始化联系人数据(显示 pending),之后每次切换到 All 列表,也会重新请求联系人数据: ![browser-result](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/08/browser-result.png) --- > 本小节的代码可以在[这里查看](https://github.com/modern-js-dev/modern-js-examples/tree/main/tutorials/c09/hello-modern-3)。