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