CSS-in-JS 方案使样式随组件加载生效并自动清理,支持作用域绑定、SSR 同步、动态主题响应及卸载清理,主流库如 Emotion 和 Styled-Components 通过生命周期钩子与缓存机制保障样式精准注入与复用。

组件样式随组件加载,关键在于确保样式只在组件挂载时生效、卸载时清理(尤其在 SSR 或动态加载场景下),而 CSS-in-JS 方案天然支持这种“作用域 绑定”和“生命周期联动”。主流库如 Emotion、Styled-Components、JSS 都能实现样式与组件的强耦合,无需手动管理 link 标签或 class 冲突。
样式随组件实例化自动注入
CSS-in-JS 库在组件首次渲染时,会将 JS 中定义的样式规则转为真实 CSS,并插入到 中(或通过 <style></style> 标签动态挂载)。该过程由组件调用触发,不依赖外部文件加载顺序。
- Emotion 的
css或styled函数:每次调用生成唯一 className 和对应样式规则,仅当组件 render 时执行 - Styled-Components 的
styled.xxx组件:底层使用useInsertionEffect(React 18+)或useLayoutEffect确保样式在 DOM 渲染前就位 - 样式不会提前全局污染,也不会因组件未渲染而冗余注入
服务端渲染(SSR)中保持样式同步
服务端需提取当前页面所有组件用到的样式,拼成 <style></style> 字符串,随 HTML 一同下发;客户端 hydration 时复用已有样式,避免 FOUC 或重复插入。
- Emotion 提供
CacheProvider+createCache({key: 'emotion'}),配合extractCritical(Node 环境)或cache.sheet.toString()(客户端)提取样式 - Styled-Components 使用
ServerStyleSheet在服务端收集、collectStyles包裹组件树,再注入到 HTML 模板中 - 关键点:服务端和客户端必须使用相同的 cache key 或 sheet 实例,否则样式无法复用
动态主题 / 条件样式随组件状态响应更新
CSS-in-JS 天然支持运行时计算样式。组件内 props、theme、hooks 状态变化时,样式函数重新执行,生成新规则并替换旧规则(或新增)。
立即学习 “ 前端免费学习笔记(深入)”;
- 例如:
const Button = styled.button(({theme, variant}) => ({backgroundColor: theme.colors[variant] })) - Emotion 的
css支持传入函数,参数为{theme},自动订阅 theme 变化 - 样式更新不操作 DOM class 列表,而是直接切换已注入的 CSS 规则(通过 className 变更指向不同规则)
卸载时自动清理(可选,取决于库和配置)
多数 CSS-in-JS 库默认不主动删除已注入样式(因复用成本低且影响性能),但可通过配置或手动方式控制:
- Emotion 支持
cache.insertionPoint指向特定<style></style>节点,便于按需清空子节点 - Styled-Components 在严格模式或测试环境可通过
StyleSheet.reset()清除全部 - 若组件频繁挂载 / 卸载且样式差异大,建议用
key强制重置组件实例,让样式逻辑自然重建
不复杂但容易忽略:确保 babel 插件(如 @emotion/babel-plugin 或 babel-plugin-styled-components)已启用,才能把静态样式提升、压缩并启用标签模板优化。没有它,样式仍可用,但失去 source map、label 命名、自动 label 等调试与性能优势。