styled-components 保持便捷性的原因
回想大约七年前 React 中的布局方式。我们曾徒劳地尝试通过 BEM 隔离 CSS 类,后来转向 CSS Modules,随后 styled-components 应运而生。最初直接在 JS 文件中编写样式的想法看似疯狂,但 JavaScript 模板字符串迅速将这种方法转变为 Web 开发的标准之一。
如今 Tailwind CSS 和原子化 CSS 框架大行其道。与此同时,styled-components 仓库已在 GitHub 上获得超过 41,000 颗星标并持续更新。开发者们仍在积极使用它进行布局,项目维护者也在适配代码以支持当前的 React 功能,包括 React Server Components (RSC)。
为什么用标签模板取代熟悉的 CSS
该库的概念很简单:创建一个已包含所有必要样式的 React 组件。无需设计复杂的类层次结构,也不必担心基础按钮样式会意外破坏应用另一侧的模态框。
语法保持简洁的 CSS,无需在每行后添加引号和逗号:
import styled from 'styled-components';
const Button = styled.button`
background: ${props => props.$primary ? "#0070f3" : "#ffffff"};
color: ${props => props.$primary ? "#ffffff" : "#0070f3"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid #0070f3;
border-radius: 3px;
`;
export default function App() {
return (
<div>
<Button>Обычная кнопка</Button>
<Button $primary>Акцентная кнопка</Button>
</div>
);
}
样式与组件紧密绑定。从项目中移除 Button,其样式也随之消失。最终构建中不会留下未使用的代码。
Props、主题和动态外观
CSS-in-JS 的优势体现在视觉表现直接依赖数据或应用状态的地方。使用 CSS Modules 时,你需要通过 classnames 工具不断切换类名。而在这里,props 可以直接传入样式块。
传递参数而不与 DOM 冲突
注意上面示例中的 $primary 语法。美元符号表示瞬态 props。以此方式标记的变量在样式内部使用,但库会将其过滤掉,不会传递给最终的 HTML 标签。浏览器控制台保持干净,不会出现关于未知属性的警告。
内置主题支持
对于处理亮色和暗色主题,有 ThemeProvider 组件。它使用 React Context 将设置对象向下传递到组件树中。
import styled, { ThemeProvider } from 'styled-components';
const theme = {
colors: {
main: '#0070f3',
background: '#f4f4f4',
}
};
const Container = styled.div`
color: ${props => props.theme.colors.main};
background: ${props => props.theme.colors.background};
`;
在 theme 对象中替换颜色,界面会立即更新。这大大简化了设计系统的构建。
性能和服务器端渲染
该库自动追踪页面上当前显示的组件,并仅加载它们的样式。用户无需下载额外的代码。
此前,CSS-in-JS 方案因 hydration 期间的额外加载和 SSR 问题而受到批评。在最新版本中,团队重写了内部逻辑。该库可以配合流式 SSR 使用,并与 React Server Components 良好协作。样式直接嵌入 HTML 流中而不会产生延迟。
何时使用 styled-components
以下四种场景中该库表现最佳:
- 你正在构建需要灵活定制的内部 UI 组件库或设计系统。
- 项目中包含许多视觉状态根据输入数据变化的复杂交互元素。
- 团队熟悉经典 CSS 语法,但希望获得可靠的样式隔离而无需配置构建工具。
- 你正在编写跨平台项目,使用 React 和 React Native,期望使用单一 API 来处理样式。
如果你的优先考虑是在低功耗设备上启动应用并需要最小的 JS 包体积,你可能需要考虑 Tailwind CSS 或零运行时方案,如 Linaria 和 Pigment CSS。
styled-components 仍然是一个清晰且可预测的解决方案。该库消除了类名命名的麻烦,让你在组件体内直接使用纯净的 CSS。对于大多数前端任务来说,这个工具的功能已经足够强大。
相关项目