1 Star 1 Fork 0

fisher / styledfc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

StyledFc

一个简单的运行时css-in-js库,用于封装react组件

  • 零依赖
  • 非常小,< 3kb.
  • 运行时生成css
  • 支持css变量
  • 支持类似less的嵌套css样式
  • 支持props动态css
  • 支持三种使用方式
  • 支持typescript

演示

安装

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参数来指定styleIdclassName

<style id="6rxqfu">
.sw6y3s4{
    position:relative;
    width:100%;
    border:1px solid #ccc;
    border-radius:4px;
}
</style>

嵌套样式

接下来我们来为Card组件的titlefooter添加样式.

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"
      }
  })
  • 以上我们为titlefooter添加了样式。
  • 使用&符号来表示当前父类元素,使用的方式与lesssass等嵌套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属性值。

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-colorcss变量。
  • 然后我们在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>
    )
  }

Hook

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钩子返回classNamegetStyle,用来注入样式类名和动态样式。
  • getStyle函数支持传入更新css变量。如果使用到props动态样式,则需要传入props参数。
  • useStyle钩子支持传入options参数来配置styleIdclassName
  • useStylestyled函数功能一样,唯一的区别是useStylehead注入的样式表在组件卸载时会自动移除。

创建样式组件

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({...})

API

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)
MIT License Copyright (c) 2024 fisher Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

一个非常小的css-in-js构建react组件的库 展开 收起
JavaScript 等 4 种语言
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/zhangfisher/styledfc.git
git@gitee.com:zhangfisher/styledfc.git
zhangfisher
styledfc
styledfc
master

搜索帮助