UNPKG

rerumaccusamus

Version:

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

107 lines (84 loc) 4.23 kB
--- title: 容器组件(Container) --- 前两个章节中,我们把项目中的业务逻辑拆分成了两个 layer,一个是【 视图组件 】,另一个是 【 业务模块 】。 【 视图组件 】 负责 UI 展示、交互等;【 业务模块 】负责实现 UI 无关的业务逻辑,专门管理状态,既可以是组件状态(局部,不唯一),也可以是应用状态(全局,唯一)。 像 `components/Contacts/index.tsx` 这样使用了 `useModel` API 的组件,其实已经在**客户端应用架构**中扮演一种新的角色,负责把 ViewModel 这两个 layer 连接起来,类似传统 MVC 架构中 Controller 的角色,也类似一种 ViewController。 因为这种组件属于一种新的功能模块,在 Modern.js 里我们沿用习惯,把它们称作【 容器组件(Container)】。 容器组件推荐放在专门的 `containers/` 目录里,我们执行以下命令: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; <Tabs> <TabItem value="macOS" label="macOS" default> ```bash mkdir -p src/contacts/containers/ mv src/contacts/components/Contacts/index.tsx src/contacts/containers/Contacts.tsx rm -r src/contacts/components/Contacts/ ``` </TabItem> <TabItem value="Windows" label="Windows"> ```powershell mkdir -p src/contacts/containers/ mv src/contacts/components/Contacts/index.tsx src/contacts/containers/Contacts.tsx rm -r src/contacts/components/Contacts/ ``` </TabItem> </Tabs> 修改 `containers/Contacts.tsx` 的代码: ```tsx import Item from '../components/Item'; import contacts from '../models/contacts'; ``` 修改 `App.tsx` 的代码: ```tsx import Contacts from './containers/Contacts'; ``` 重构完成,现在的项目结构是: ```md . ├── .vscode/ ├── api/ │ ├── .eslintrc.json │ └── contacts.ts ├── src/ │ ├── contacts/ │ │ ├── components/ │ │ │ ├── Avatar/ │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ └── Item/ │ │ │ ├── index.test.tsx │ │ │ └── index.tsx │ │ ├── containers/ │ │ │ └── Contacts.tsx │ │ ├── models/ │ │ │ ├── contacts.test.ts │ │ │ └── contacts.ts │ │ ├── styles/ │ │ │ └── utils.css │ │ ├── App.css │ │ └── App.tsx │ ├── landing-page/ │ │ └── pages/ │ │ ├── comments/ │ │ │ └── [commentTitle]/ │ │ │ └── index.tsx │ │ ├── _app.tsx │ │ ├── docs.tsx │ │ └── index.tsx │ ├── .eslintrc.json │ └── modern-app-env.d.ts ├── .editorconfig ├── .gitignore ├── .npmrc ├── .nvmrc ├── README.md ├── package.json ├── pnpm-lock.yaml └── tsconfig.json ``` `components/` 里的【 视图组件 】,都是目录形式,如 `Avatar/index.tsx`。而 `containers/` 里的【 容器组件 】,都是单文件形式,如 `contacts.tsx`。**这是我们推荐的一种最佳实践**。 在​ [添加 UI 组件(Component)](../c06-css-and-component/6.1-css-in-js.md) 章节提到过,【 视图组件 】用目录形式,是因为【 视图组件 】负责实现 UI 展示和交互细节,可以演变的复杂,用目录形式,可以方便增加子文件,包括专用的资源(图片等)、专用子组件、CSS 文件等,在这个目录内部可以随意重构,只考虑最小局部。 而【 容器组件 】只负责连接,是一个胶水层,复杂的业务逻辑和实现细节都交给 View 层和 Model 层去实现,【 容器组件 】自己应该保持简单清晰,不应该包含复杂实现细节,所以不应该有内部结构,采用单文件形式不但更简洁,也能起到约束作用,提醒开发者不要把容器组件写复杂。 --- > 本小节的代码可以在[这里查看](https://github.com/modern-js-dev/modern-js-examples/tree/main/tutorials/c11/hello-modern-2)。