代码拉取完成,页面将自动刷新
一个简单的运行时css-in-js
库,用于封装react
组件
pnpm add styledfc
# or
npm install styledfc
# or
yarn add styledfc
拟开发一个Card
组件,组件有一个title
属性,用于显示标题,一个footer
属性,用于显示底部内容,children
属性作为卡片的内容区。
import { styled } from "styledfc"
export type CardProps = React.PropsWithChildren<{
title:string
footer?:string
}>
export const Card = styled<CardProps>((props,{className})=>{
const { title,children,footer} =props
return (
<div className={className}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)
},{ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px"
})
Card
组件,为样式生成一个样式类(名称是随机生成的)并插入到head
标签中。className
属性传递给组件,组件将使用这个类名来应用样式。实际上,你可以在head
发现一个类似这样的CSS
样式,其中的类名
和style.id
均是自动生成的。也可以通过options
参数来指定styleId
和className
。
<style id="6rxqfu">
.sw6y3s4{
position:relative;
width:100%;
border:1px solid #ccc;
border-radius:4px;
}
</style>
接下来我们来为Card
组件的title
和footer
添加样式.
export const Card = styled<CardProps>((props,{className})=>{
const { title,children,footer} =props
return (
<div className={className}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
}
})
title
和footer
添加了样式。&
符号来表示当前父类元素,使用的方式与less
和sass
等嵌套CSS的语法类似。在head
生成的样式如下:
<style id="6rxqfu">
.sw6y3s4{
position:relative;
width:100%;
border:1px solid #ccc;
border-radius:4px;
}
.sw6y3s4 > .title{
font-size:20px;
font-weight:bold;
}
.sw6y3s4 > .footer{
border-top:1px solid #ccc;
padding:8px;
text-align:right;
}
</style>
styledfc
支持使用props
来动态设置样式。
我们想让卡片content
的背景颜色可以通过props.bgColor
属性来指定。
export const Card = styled<CardProps>((props,{className,getStyle})=>{
const { title,children,footer} =props
return (
<div className={className} style={getStyle()}>
<div className="title">
{title}
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})
getStyle
函数来获取动态样式,然后注入到组件的根元素中。getStyle
函数返回一个css
样式对象,可以直接传递给style
属性。css
属性均可以使用(props)=>{....}
来动态生成CSS属性值。styledfc
支持使用css
变量。可以在getStyle
函数中传入更新后的css
变量。
export const Card = styled<CardProps>((props,{className,getStyle})=>{
const { title,children,footer} =props
const [primaryColor,setPrimaryColor] = React.useState("blue")
return (
<div className={className} style={getStyle({"--primary-color":primaryColor})}>
<div className="title">
{title}<button onClick={()=>setPrimaryColor('red')}>
</div>
<div className="content">{children}</div>
<div className="footer">{footer}</div>
</div>
)},{ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"--primary-color":"blue",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
color:"var(--primary-color)"
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})
--primary-color
的css
变量。title
样式中使用了--primary-color
变量。getStyle
函数支持传入更新css
变量。styled
函数也可以只用来创建样式并插入到HEAD
。
// card.style.ts
import { styled } from "styledfc"
// 创建样式并插入到head
export default styled({ // 组件样式
position:"relative",
width:"100%",
border:"1px solid #ccc",
borderRadius:"4px",
"--primary-color":"blue",
"& > .title":{
fontSize:"20px",
fontWeight:"bold",
color:"var(--primary-color)"
},
"& > .footer":{
borderTop:"1px solid #ccc",
padding:"8px",
textAlign:"right"
},
"& > .content":{
padding:"8px",
backgroundColor:(props)=>props.bgColor
}
})
// card.tsx
import cardStyle from "./card.style"
export default (props:CardProps)=>{
return (
<div className={cardStyle.className} style={cardStyle.getStyle({"--title-color":titleColor},props)}>
<div className="title">
{props.title}
</div>
<div className="content">{props.children}</div>
<div className="footer">{props.footer}</div>
</div>
)
}
styledfc
还提供了一个useStyle
钩子,用于在函数组件中使用。
同样功能的Card
组件可以使用useStyle
钩子来实现。
import { useStyle } from "styledfc"
export const Card2:React.FC<React.PropsWithChildren<CardProps>> = ((props:CardProps)=>{
const { title } = props
const [titleColor,setTitleColor] = useState("blue")
const {className,getStyle } = useStyle({
// 此处是组件样式
})
return (
<div className={className} style={getStyle({"--title-color":titleColor},props)}>
<div className="title">
<span>{title}</span>
<span className="tools"><button onClick={()=>setTitleColor(getRandColor())}>Change</button></span>
</div>
<div className="content">
{props.children}
</div>
<div className="footer">{props.footer}</div>
</div>
)
})
useStyle
钩子返回className
和getStyle
,用来注入样式类名和动态样式。getStyle
函数支持传入更新css
变量。如果使用到props
动态样式,则需要传入props
参数。useStyle
钩子支持传入options
参数来配置styleId
和className
。useStyle
与styled
函数功能一样,唯一的区别是useStyle
在head
注入的样式表在组件卸载时会自动移除。从1.1.0
版本开始,styledfc
支持创建样式组件。
import { styled } from "styledfc"
const MyButton = styled.div({
color:"red",
"&:hover":{
color:"blue"
}
})
// 其他如styled.span,styled.button等任意有效的HTML tag
styledfc
支持以下options
参数来配置。
// styled(<React.FC>,<styles>,<options>)
export interface StyledOptions{
// 样式表的ID,没有指定则会自动生成
styleId?:string
// 生成的样式类名,如果没有指定则自动生成
className?:string
}
由于css-in-js
的限制,可能会存在性能问题,一个推荐的性能优化方式是:在应用的启动阶段,将所有的样式一次性创建并插入到head
中,然后在组件中来引用样式。
// styles.tsx
import { styled } from "styledfc"
export style1 = styled({...})
export style2 = styled({...})
export style3 = styled({...})
export interface StyledOptions{
// 生成的样式表id,如果没有指定则自动生成
styleId?:string
// 生成的css类名,如果没有指定则自动生成
className?:string
}
export type StyledComponentParams ={
// 生成的css类名
className:string
// 生成的样式表id
styleId:string
// css变量
vars:Record<string,string | number>
// 获取动态css样式,当使用props动态css时需要使用getStyle注入css样式对象,例如style={getStyle()}
getStyle : ()=>Record<string,string | number>
}
export type StyledComponent<Props> = (props:React.PropsWithChildren<Props>,params:StyledComponentParams)=>React.ReactElement
//
styled<Props>(FC: StyledComponent<Props>,styles:CSSObject,options?:StyledOptions)
styled<Props>(styles:CSSObject,options?:StyledOptions)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型