文档知识库教程开发工具【免费下载链接】reference为开发人员分享快速参考备忘清单(速查表)项目地址https://gitcode.com/jaywcjlove/reference点击查看免费下载本指南以 jaywcjlove/reference 仓库中的 docs/styled-components.md 为主体系统梳理 CSS-in-JS 工具 styled-components 在 React 组件系统中的全部常用技法。从安装、基础组件创建、Props 适配、样式扩展到 TypeScript 类型方案、React Native 写法与主题化高级用法读完本文你将能独立用 styled-components 写出类型安全、可复用、可主题化的组件样式。入门安装styled-components 是增强 CSS 在 React 组件系统样式的 CSS-in-JS 主流实践方案。它允许你在 JavaScript/TypeScript 中直接书写真正的 CSS并将其绑定到组件上同时自动处理样式作用域隔离、关键帧命名和样式注入。安装运行时依赖与 TypeScript 类型依赖npm install --save styled-components为获得更好的开发体验可搭配官方维护的编辑器插件均提供语法高亮部分支持自动补全VSCode 插件提供代码高亮与代码提示styled-components 官方维护VIM 插件提供代码高亮WebStorm 插件提供代码高亮与代码提示快速开始在组件文件中引入 styled 默认导出import styled from styled-components;创建一个 Title 组件// 该组件将呈现具有样式的 h1 标签 const Title styled.h1 font-size: 1.5em; text-align: center; ;创建一个 Wrapper 组件// 该组件将呈现具有某些样式的 section 标记 const Wrapper styled.section padding: 4em; background: papayawhip; ;像使用其他 React 组件一样使用 Title / Wrapper —— 除了它们自带样式function Demo() { return ( Wrapper Title Hello World! /Title /Wrapper ); }这里styled.h1、styled.section是通过标签模板tagged template语法接收 CSS 字符串的工厂函数返回一个带着样式的 React 组件。底层通过为组件生成稳定的唯一类名并将样式规则注入head从而实现样式与组件的一一对应。根据 Props 适配样式模板内的插值函数会接收组件自身的props据此动态产出 CSS这是 styled-components 实现状态驱动样式的核心机制import styled from styled-components; const Button styled.button /* 根据主要 props 调整颜色 */ background: ${ props props.primary ? blue : white }; color: ${ props props.primary ? white : blue }; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid blue; border-radius: 3px; ;使用primaryprops 控制按钮样式function Demo() { return ( div ButtonNormal/Button Button primaryPrimary/Button /div ); }当primary为真时按钮呈现蓝底白字否则为白底蓝字。插值函数接收到的props与组件渲染时的 props 完全一致因此可以读取任意自定义属性来做条件样式。扩展样式基于已有 styled 组件创建新组件新组件继承原组件全部样式再叠加或覆盖新规则。这种继承是样式层面上的类继承非常适合构建基础组件库const Button styled.button color: palevioletred; border: 2px solid palevioletred; border-radius: 3px; ; // 基于 Button 的新组件但具有一些覆盖样式 const TomatoButton styled(Button) color: tomato; border-color: tomato; ; const Demo () ( div Button普通按钮/Button TomatoButton番茄色按钮/TomatoButton /div );styled(Button)接收一个已存在的组件作为目标返回继承其样式的增强组件。扩展样式改变标签 (as)通过as属性可以在不改变既有样式的前提下把渲染的 DOM 标签切换为其他标签。例如让button以a的形式渲染样式完全不变const Button styled.button color: palevioletred; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; display: block; ; const TomatoButton styled(Button) color: tomato; border-color: tomato; ; const Demo () ( div Button普通按钮/Button Button asa href# 按钮样式的链接 /Button TomatoButton asa href# 番茄按钮样式的链接 /TomatoButton /div );as也可以用于扩展出来的组件如TomatoButton灵活组合标签与样式。自定义组件(as)as除了接收字符串标签名还可以接收任意自定义 React 组件。此时自定义组件将获得 styled 组件生成的 className并沿用其全部样式const Button styled.button color: palevioletred; font-size: 1em; border: 2px solid palevioletred; display: block; ; const ReversedButton props ( Button {...props} children{ props.children.split().reverse() } / ); render( div Button普通按钮/Button Button as{ReversedButton} 具有普通按钮样式的自定义按钮 /Button /div );ReversedButton作为自定义组件接收了 Button 的样式类同时自身实现了把子文本倒序显示的额外逻辑——样式与行为被优雅地解耦。样式化任何组件任何接收className属性的组件都可以被 styled 化。关键约定目标组件必须把className透传到其渲染的真实 DOM 元素上否则样式无法生效const Link ({ className, children }) ( a className{className} {children} /a ); const StyledLink styled(Link) color: palevioletred; font-weight: bold; ; StyledLink classNamehello /这也是编写可被 styled 化的第三方/自有组件的通用模式通过className入口承接外部样式。在 render 之外定义 Styled 组件styled 组件必须在模块顶层或 render 之外定义绝不能在组件函数体内创建const Box styled.div/* ... */; const Wrapper ({ message }) { // ⚠️ 不能在这里定义 styled 组件 return ( Box {message} /Box ); };注意组件Box不能放到Wrapper函数组件里面。原因在于 styled 组件内部依赖稳定的组件身份component identity做缓存、class 生成与样式去重每次 render 都重新创建会导致 React 卸载/重挂载整个子树产生样式闪烁与性能退化。传入值把外部传入的值通过 props 插值直接写入样式未传时使用默认值const Input styled.input color: ${ props props.inputColor || palevioletred }; background: papayawhip; ; const Demo () ( div Input defaultValueprobablyup typetext / Input defaultValuegeelen typetext inputColorrebeccapurple / /div );未传inputColor的第一个输入框使用默认色palevioletred传了inputColorrebeccapurple的第二个输入框则使用自定义颜色。样式对象插值函数也可以直接返回一个 CSS 属性对象camelCase 键名而不是 CSS 字符串const PropsBox styled.div(props ({ background: props.background, height: 50px, width: 50px, fontSize: 12px }));在组件中使用const Example () { return ( div PropsBox backgroundblue / /div ); }注意样式对象里面的键名并不是 CSS 中的写法font-size要写成fontSize而是遵循 JavaScript 对象属性的 camelCase 规则。CSSModules styledCSS Modules 需要为每个节点手工维护styles.xxx类名引用迁移到 styled-components 后样式与组件合并为一个声明去掉了类名桥接层。下面的计数器组件是两种写法的等效对照。CSS Modules 写法import React, { useState } from react; import styles from ./styles.css; function ExampleCounter() { const [count, setCount] useState(0) return ( div className{styles.counter} p className{styles.paragraph} {count} /p button className{styles.button} onClick{() setCount(count 1)} /button button className{styles.button} onClick{() setCount(count -1)} - /button /div ); }与下面 styled 写法等效import styled from styled-components; const StyledCounter styled.div /* ... */ ; const Paragraph styled.p /* ... */ ; const Button styled.button /* ... */ ; function ExampleCounter() { const [count, setCount] useState(0); const increment () { setCount(count 1); } const decrement () { setCount(count -1); } return ( StyledCounter Paragraph{count}/Paragraph Button onClick{increment} /Button Button onClick{decrement} - /Button /StyledCounter ); }两种方案产出的 DOM 结构完全一致styled 版本把选择器 样式收敛进了组件本身。伪元素、伪选择器和嵌套styled-components 内置了类似 Sass 的嵌套语法表示当前组件自身的选择器可组合出各种伪类与上下文选择器const Thing styled.div.attrs((/* props */) ({ tabIndex: 0 })) color: blue; :hover { /* Thing 悬停时 */ color: red; } ~ { /* Thing 作为 Thing 的兄弟但可能不直接在它旁边 */ background: tomato; } { /* Thing 旁边的 Thing */ background: lime; } .something { /* Thing 标记有一个额外的 CSS 类 .something */ background: orange; } .something-else { /* Thing 在另一个标记为 .something-else 的元素中 */ border: 1px solid; } ; render( React.Fragment ThingHello world!/Thing Thing你怎么样/Thing Thing classNamesomething 艳阳高照... /Thing div今天真是美好的一天。/div Thing你不觉得吗/Thing div classNamesomething-else Thing灿烂/Thing /div /React.Fragment );各选择器含义归纳选择器写法作用:hover组件自身悬停时 ~ 作为另一个 Thing 的兄弟节点不一定相邻 紧邻另一个 Thing 的兄弟节点.something组件同时带有额外类.something.something-else 组件位于带.something-else类的祖先元素内部改变 styled 组件样式在插值函数里通过css助手与双组合出仅针对当前组件的高优先级选择器实现引用其他 styled 组件并精准覆盖其样式import { css } from styled-components import styled from styled-components const Input styled.input.attrs({ type: checkbox }); const LabelText styled.span ${(props) { switch (props.$mode) { case dark: return css color: white; ${Input}:checked { color: blue; } ; default: return css color: black; ${Input}:checked { color: red; } ; } }} ; function Example() { return ( React.Fragment Label Input defaultChecked / LabelTextFoo/LabelText /Label Label Input / LabelText $modedark Foo /LabelText /Label /React.Fragment ); }${Input}会在选择器中展开为 Input 组件的类名则会重复当前组件类名以提升特异性从而覆盖来自其他位置的同类规则。全局样式 createGlobalStyle与组件级样式不同createGlobalStyle用于注入全局样式如 reset、字体、主题变量。它渲染时不产生任何 DOM 节点只把样式注入全局import { styled, createGlobalStyle } from styled-components const Thing styled.div { color: blue; } ; const GlobalStyle createGlobalStyle div${Thing} { color: red; } ; const Example () ( React.Fragment GlobalStyle / Thing 我是蓝色的 /Thing /React.Fragment );div${Thing}表示包含了 Thing 类名的 div选择器。由于组件自身的特异性更高Thing仍显示为蓝色。className 使用styled 组件的样式内也可以嵌套普通类选择器用来给子元素如 label施加样式无需为该子元素单独创建 styled 组件const Thing styled.div color: blue; /* Thing 中标记为.something的元素 */ .something { border: 1px solid; } ; function Example() { return ( Thing label htmlForfoo-button classNamesomething 神秘按钮 /label button idfoo-button 我该怎么办 /button /Thing ) }当组件需要接收外部className时styled 组件会自动把外部类与生成类合并到根元素上因此这里的classNamesomething能命中嵌套规则。共享样式片段当一段样式需要跨组件复用或需要把关键帧等动态值拼进模板时必须使用css助手包裹而不是普通字符串拼接const rotate keyframes from {top:0px;} to {top:200px;} ; // ❌ 这将引发错误 const styles animation: ${rotate} 2s linear infinite; ; // ✅ 这将按预期工作 const styles css animation: ${rotate} 2s linear infinite; ;原因模板字符串会把rotate强制转成字符串破坏关键帧对象引用css助手会保留插值结构交给编译器做正确的解析与去重。Class 组件样式定义class 组件必须把this.props.className渲染到实际的 DOM 节点上才能被 styled 化并接收外部样式class NewHeader extends React.Component { render() { return ( div className{this.props.className} / ); } } const StyledA styled(NewHeader) const Box styled.div ${StyledA} { /* 变更 NewHeader 样式 */ } ;styled(NewHeader) 创建出可被引用的StyledA随后在Box内通过${StyledA} 选择器对它做定向样式变更。附加额外的 Propsattrs用于给组件预设静态或动态计算的props被预设的 props 会自动应用到 DOM 节点上并且可以在样式插值中直接使用const Input styled.input.attrs(props({ // 我们可以定义静态道具 type: text, // 或者我们可以定义动态的 size: props.size || 1em, })) color: palevioletred; font-size: 1em; border: 2px solid palevioletred; border-radius: 3px; /* 这里我们使用动态计算的 props */ margin: ${props props.size}; padding: ${props props.size}; ;使用Input组件function Example() { return ( div Input placeholder小文本输入 / br / Input placeholder更大的文本输入 size2em / /div ) }未传size时默认1em传入size2em时边距随之放大同时type始终被预设为text。覆盖 .attrs对已带attrs的组件继续调用.attrs后者的预设会覆盖前者且预设的 props 可以继续在派生组件里使用const Input styled.input.attrs(props({ type: text, size: props.size || 1em, })) border: 2px solid palevioletred; margin: ${props props.size}; padding: ${props props.size}; ; // Input 的attrs会先被应用然后这个 attrs obj const PasswordInput styled(Input).attrs({ type: password, }) /* 同样border 将覆盖 Input 的边框 */ border: 2px solid aqua; ;使用Input和PasswordInput组件render( div Input placeholder更大的文本输入 size2em / br / {/*⚠️ 仍然可以使用Input中的 size attr*/} PasswordInput placeholder更大的密码输入 size2em / /div );PasswordInput的type被覆盖为password但依然继承并使用Input定义的size动态预设。动画通过keyframes定义关键帧再在组件样式中通过插值引用创建关键帧const rotate keyframes from { transform: rotate(0deg); } to { transform: rotate(360deg); } ;创建一个Rotate组件// 它将在两秒内旋转我们传递的所有内容 const Rotate styled.div display: inline-block; animation: ${rotate} 2s linear infinite; padding: 2rem 1rem; font-size: 1.2rem; ;使用Rotate组件function Example() { return ( Rotatelt; gt;/Rotate ) }keyframes返回的对象同样需要像css一样通过插值嵌入模板不能字符串拼接styled-components 会自动生成唯一动画名并注入keyframes规则。isStyledComponent当面对一个可能是 styled 组件的模块时用isStyledComponent做运行时判断决定是直接使用还是包装成 styled 组件import React from react import styled, { isStyledComponent } from styled-components import MaybeStyledComponent from ./my let TargetedComponent isStyledComponent(MaybeStyledComponent) ? MaybeStyledComponent : styled(MaybeStyledComponent); const ParentComponent styled.div color: cornflowerblue; ${TargetedComponent} { color: tomato; } ;这段代码保证了TargetedComponent一定是一个 styled 组件从而可以在${TargetedComponent}选择器中安全引用。ThemeConsumer不通过组件样式访问主题而是直接在渲染函数中消费主题值import { ThemeConsumer } from styled-components function Example() { return ( ThemeConsumer {theme ( div主题色是 {theme.color}/div )} /ThemeConsumer ); }ThemeConsumer使用 render props 模式把当前主题对象作为参数传给子函数。TypeScript安装Web 应用上安装类型定义npm install -D types/styled-componentsReact Native 应用上安装类型定义npm install -D \ types/styled-components \ types/styled-components-react-native如果对 TypeScript 不熟悉可以参考本仓库的 TypeScript 备忘清单。自定义 Props通过泛型参数为 styled 组件声明 props 类型插值函数中的props即获得类型推导import styled from styled-components; interface TitleProps { readonly isActive: boolean; } const Title styled.h1TitleProps color: ${(props) ( props.isActive ? props.theme.colors.main : props.theme.colors.secondary )}; ;props.theme的类型由 ThemeProvider 注入的主题对象推导isActive则由TitleProps声明二者都获得完整的编译期检查。简单的 Props 类型定义针对扩展已有组件的场景同样可以用泛型声明新增 propsimport styled from styled-components; import Header from ./Header; const Header styled.header font-size: 12px; ; const NewHeader styled(Header){ customColor: string; } color: ${(props) props.customColor}; ;NewHeader在继承Header样式的基础上新增了必填的customColor字符串属性。禁止转移到子组件($)默认情况下传给 styled 组件的非 HTML 原生属性会被透传到真实 DOM。若不想让自定义属性出现在 DOM 上可在属性名前加美元符号$styled-components 会识别并阻止其转移到子组件import styled from styled-components; import Header from ./Header; interface ReHeader { $customColor: string; } const ReHeader styled(Header)ReHeader color: ${ props props.$customColor }; ;禁止customColor属性转移到Header组件在其前面加上美元($)符号即可。$前缀是 v5 起推荐的瞬态 proptransient prop约定既满足样式计算需求又避免污染 DOM 属性如出现customcolor...之类的非法属性警告。函数组件类型继承用 React 内置的 HTML 属性类型DetailedHTMLProps、ImgHTMLAttributes扩展出自定义组件 props再封装为带完整类型的高阶组件import { FC, PropsWithRef, DetailedHTMLProps, ImgHTMLAttributes } from react; import styled from styled-components; const Img styled.img height: 32px; width: 32px; ; export interface ImageProps extends DetailedHTMLProps ImgHTMLAttributesHTMLImageElement, HTMLImageElement { text?: string; }; export const Image: FCPropsWithRefImageProps (props) ( Img src alt {...props} / );ImageProps继承原生img的全部属性并追加可选的自定义text字段通过{...props}展开后所有合法属性都会被透传。React Native基础实例在 React Native 中从styled-components/native导入即可使用styled.View、styled.Text等内建组件工厂import React from react import styled from styled-components/native const StyledView styled.View background-color: papayawhip; ; const StyledText styled.Text color: palevioletred; ; class MyReactNativeComponent extends React.Component { render() { return ( StyledView StyledTextHello World!/StyledText /StyledView ); } }与 Web 版 API 完全一致只是目标组件来自 React Native 而非 DOM 标签。React Native 中写 CSSReact Native 样式遵循 RN 的样式子集可写transform、text-shadow-offset、font-variant等 RN 支持属性import styled from styled-components/native const RotatedBox styled.View transform: rotate(90deg); text-shadow-offset: 10px 5px; font-variant: small-caps; margin: 5px 7px 2px; ; function Example() { return ( RotatedBox / ) }与 web 版本的区别不能使用keyframes和createGlobalStyle助手因为 React Native 不支持关键帧或全局样式。如果使用媒体查询或嵌套 CSS会收到警告。高级用法主题化ThemeProvider通过 React Context 向下层组件注入主题对象样式插值函数通过props.theme消费import styled, { ThemeProvider } from styled-components // 定义我们的按钮但这次使用 props.theme const Button styled.button font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; /* 使用 theme.main 为边框和文本着色 */ color: ${props props.theme.main}; border: 2px solid ${props props.theme.main}; ; // 我们正在为未包装在 ThemeProvider 中的按钮传递默认主题 Button.defaultProps { theme: { main: palevioletred } } // 定义 props.theme 的外观 const theme { main: mediumseagreen }; render( div ButtonNormal/Button ThemeProvider theme{theme} ButtonThemed/Button /ThemeProvider /div );位于ThemeProvider之外的按钮读取defaultProps提供的默认主题位于其内部的按钮则读取注入的mediumseagreen主题。功能主题ThemeProvider的theme除了可以是对象还可以是接收外层主题并返回新主题的函数实现主题的派生与反转import styled, { ThemeProvider } from styled-components // 定义我们的按钮但这次使用 props.theme const Button styled.button color: ${props props.theme.fg}; border: 2px solid ${props props.theme.fg}; background: ${props props.theme.bg}; font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; ; // 在主题上定义我们的fg和bg const theme { fg: palevioletred, bg: white }; // 这个主题交换了fg和bg const invertTheme ({ fg, bg }) ({ fg: bg, bg: fg }); render( ThemeProvider theme{theme} div Button默认主题/Button ThemeProvider theme{invertTheme} Button反转主题/Button /ThemeProvider /div /ThemeProvider );内层ThemeProvider把函数invertTheme应用于外层主题得到前景/背景互换的新主题嵌套 Provider 支持任意层级的主题覆盖。通过 withTheme 高阶组件class 组件无法直接使用 hooks可通过withTheme高阶组件把当前主题作为props.theme注入import { withTheme } from styled-components class MyComponent extends React.Component { render() { console.log(Current theme: , this.props.theme) // ... } } export default withTheme(MyComponent)useContext 钩子函数组件可以直接使用 React 的useContext消费 styled-components 导出的ThemeContextimport { useContext } from react import { ThemeContext } from styled-components const MyComponent () { const themeContext useContext(ThemeContext) console.log(Current theme: , themeContext) // ... }useTheme 自定义钩子styled-components 提供了封装好的useTheme钩子是函数组件读取主题最简洁的方式import {useTheme} from styled-components const MyComponent () { const theme useTheme() console.log(Current theme: , theme) // ... }主题 props主题可以按就近覆盖的粒度应用单个组件可通过theme属性直接传入主题覆盖 Provider 层级的主题值import { ThemeProvider, styled } from styled-components; // 定义我们的按钮 const Button styled.button font-size: 1em; margin: 1em; padding: 0.25em 1em; /* 使用 theme.main 为边框和文本着色 */ color: ${props props.theme.main}; border: 2px solid ${props props.theme.main}; ; // 定义主题的外观 const theme { main: mediumseagreen };使用自定义主题组件render( div Button theme{{ main: royalblue }} 特设主题 /Button ThemeProvider theme{theme} div ButtonThemed/Button Button theme{{ main: darkorange }} 被覆盖 /Button /div /ThemeProvider /div );直接传theme的组件优先级最高royalblue应用于无 Provider 的按钮darkorange覆盖了 Provider 注入的mediumseagreen。Refsstyled 组件照常转发refReact 16.3 的 createRef 或函数 ref可用来做聚焦等命令式操作import { ThemeProvider, styled } from styled-components; const Input styled.input border: none; border-radius: 3px; ; class Form extends React.Component { constructor(props) { super(props); this.inputRef React.createRef(); } render() { return ( Input ref{this.inputRef} placeholderHover to focus! onMouseEnter{() { this.inputRef.current.focus() }} / ); } }使用Form组件function Example() { return ( Form / ) }鼠标移入输入框时onMouseEnter触发this.inputRef.current.focus()实现悬停聚焦。特异性问题styled 组件生成的类选择器通常带有较高特异性外部普通类名难以覆盖。假设在文件MyComponent.js中定义组件const MyComponent styled.div background-color: green; ;定义样式my-component.css.red-bg { background-color: red; }使用MyComponent组件MyComponent classNamered-bg /由于某种原因这个组件仍然有绿色背景即使你试图用red-bg类覆盖它解决方案提升覆盖规则的特异性将类名重复一次.red-bg.red-bg { background-color: red; }.red-bg.red-bg的双类名特异性高于单个类名即可稳定覆盖 styled 组件生成的样式。ThemeProvider最基础的 Provider 用法theme属性直接传对象被包裹组件的props.theme即可读取import styled, { ThemeProvider } from styled-components const Box styled.div color: ${props props.theme.color}; ; const Example () ( ThemeProvider theme{{ color: mediumseagreen }} BoxIm mediumseagreen!/Box /ThemeProvider );shouldForwardProp默认情况下 styled 组件会把所有非 HTML 属性透传给 DOM。用.withConfig({ shouldForwardProp })可以自定义哪些 props 应当被透传配合defaultValidatorFn保留框架默认校验逻辑const Comp styled(div).withConfig({ shouldForwardProp: (prop, defaultValidatorFn) ![hidden].includes(prop) defaultValidatorFn(prop), }).attrs({ className: foo }) color: red; .foo { text-decoration: underline; } ; const Example () ( Comp hidden draggabletrue Drag Me! /Comp );示例中拦截了hidden属性使其不落到 DOM 上同时保留 React 合法的draggable等属性正常透传attrs预设的foo类配合.foo选择器完成下划线装饰。速查要点回顾创建组件styled.h1、styled(Component)标签模板样式即组件。动态样式模板插值函数接收props支持条件样式、传入值与主题消费。复用与覆盖styled(Button)继承扩展as切换标签或自定义组件提升特异性精准覆盖。attrs预设静态/动态 props派生组件可继续覆盖。主题体系ThemeProvider对象或函数、ThemeConsumer、withTheme、useTheme、ThemeContext、组件级theme就近覆盖。TypeScript泛型声明 props、$前缀瞬态 prop、基于DetailedHTMLProps的类型继承。React Native从styled-components/native导入不支持keyframes与createGlobalStyle。注意事项styled 组件必须在 render 之外定义共享片段用css覆盖外部样式需提升特异性.red-bg.red-bg。本清单完整收录于仓库 docs/styled-components.md该文件与本仓库其他数百份速查表一样统一通过refs-cli构建为可检索的 HTML 速查站构建脚本见 package.json 的build与start命令可在浏览器中随查随用。赞分享文档知识库教程开发工具【免费下载链接】reference为开发人员分享快速参考备忘清单(速查表)项目地址https://gitcode.com/jaywcjlove/reference点击查看免费下载相关推荐styled-components 完整实战指南Reference 速查清单中的 CSS-in-JS 组件样式方案styled components 完整实战指南Reference 速查清单中的 CSS in JS 组件样式方案 本文以本仓库 styled compone文档教程styled-components在React-Boilerplate中的应用CSS-in-JS实战指南styled components在React Boilerplate中的应用CSS in JS实战指南 styled components是React生态中前端示例工程开发工具spin.js中的CSS-in-JS使用styled-components集成spin.js中的CSS in JS使用styled components集成 在现代前端开发中CSS in JS方案已经成为组件化样式管理的主流选择。本文UI组件前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
