UNPKG

rerumaccusamus

Version:

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

111 lines (76 loc) 3.55 kB
--- title: 用 CSS in JS 写组件 --- 上一章节中,我们学习了如何使用 UI 组件库、标准三方库中的组件。 这一章节中,我们将学习如何实现 UI 组件。 首先我们希望自己控制联系人头像的展示,实现这种设计稿: ![design](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/06/design1.png) 假设没有现成的组件可以实现,那就需要自己写些 CSS 了,传统上,我们有如下选择: 1. 直接在元素的 style 属性上写样式,缺点是:不方便维护,UI 视觉上的细节也会跟 UI 结构上的细节和业务逻辑混在一起。 2. 在 CSS 代码里用选择器找到这个头像元素,写样式,避免了 1 的缺点,但新的缺点是:不方便在其他有头像出现的地方复用,集中维护,做到 [DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)。 3. 在 CSS 代码里写一个 classname,封装这个样式,避免了 2 的缺点,但新的缺点是:需要考虑命名问题,避免在全局命名空间下重名,可能要用到 [BEM](http://getbem.com/) 之类的规范。 4. 用 CSS Modules 技术,让 CSS 文件和其中的 classname 变得【 模块化 】,避免了 3 的缺点。 Modern.js 开箱即用的支持 CSS Modules,但我们更推荐优先采用 CSS Modules 的继承者、在【 模块化 】上更进一步的 [styled-components](https://styled-components.com/),来实现类似的需求。 Modern.js 同样开箱即用的支持 styled-components,既不需要安装依赖,也不需要做任何配置。 在 `src/App.tsx` 里修改顶部的代码: ```js import styled from '@modern-js/runtime/styled'; ``` 添加以下代码: ```js const Avatar = styled.img` width: 50px; height: 50px; border: 4px solid #0ef; border-radius: 50%; `; ``` 修改 `List.Item.Meta` 的代码: ```tsx <List.Item.Meta avatar={<Avatar src={avatar} />} title={name} description={email} /> ``` 执行 `pnpm run dev`,可以看到预期的运行结果: ![result](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/06/result1.png) 接下来我们做一点重构,为了增强可读性,让代码更容易维护,可以把 Avatar 组件拆分出去 在终端执行以下命令: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; <Tabs> <TabItem value="macOS" label="macOS" default> ```bash mkdir -p src/components/Avatar touch src/components/Avatar/index.tsx ``` </TabItem> <TabItem value="Windows" label="Windows"> ```powershell mkdir -p src/components/Avatar ni src/components/Avatar/index.tsx ``` </TabItem> </Tabs> 把 `src/App.tsx` 里的 Avatar 实现删掉,改成: ```js import Avatar from './components/Avatar'; ``` `src/components/Avatar/index.tsx` 的内容: ```js import styled from '@modern-js/runtime/styled'; const Avatar = styled.img` width: 50px; height: 50px; border: 4px solid #0ef; border-radius: 50%; `; export default Avatar; ``` 执行 `pnpm run dev`,运行结果应该是一样的。 :::note 注 采用目录形式(Avatar/index.tsx)而不是单文件形式(Avatar.tsx)的原因是,之后可以方便在目录内部增加子文件,包括专用的资源(图片等)、专用子组件、CSS 文件等,在这个**黑盒**内部可以随意重构,只考虑**最小局部**。 ::: --- > 本小节的代码可以在[这里查看](https://github.com/modern-js-dev/modern-js-examples/tree/main/tutorials/c06/hello-modern)。