Rust的CSS-in-JS库styled_jsx的使用:为Rust项目提供高效的组件级CSS样式封装方案

Rust的CSS-in-JS库styled_jsx的使用:为Rust项目提供高效的组件级CSS样式封装方案

安装

在项目目录中运行以下Cargo命令:

cargo add styled_jsx

或者在Cargo.toml中添加以下行:

styled_jsx = "0.97.0"

基本使用

styled_jsx是一个为Rust项目提供的CSS-in-JS解决方案,它允许你在组件级别封装CSS样式,类似于React中的styled-components。以下是一个基本示例:

use styled_jsx::styled_jsx;
use yew::prelude::*;

#[function_component]
pub fn StyledButton() -> Html {
    html! {
        <>
            <button class="styled-button">
                {"点击我"}
            </button>
            {styled_jsx!(
                r#"
                .styled-button {
                    background-color: #4CAF50;
                    border: none;
                    color: white;
                    padding: 15px 32px;
                    text-align: center;
                    text-decoration: none;
                    display: inline-block;
                    font-size: 16px;
                    margin: 4px 2px;
                    cursor: pointer;
                    border-radius: 4px;
                    transition: background-color 0.3s;
                }
                
                .styled-button:hover {
                    background-color: #45a049;
                }
                "#
            )}
        </>
    }
}

完整示例

下面是一个更完整的组件示例,展示了如何使用styled_jsx来创建带有动态样式的组件:

use styled_jsx::styled_jsx;
use yew::prelude::*;

#[derive(Properties, PartialEq)]
pub Props {
    #[prop_or_default]
    pub primary: bool,
    #[prop_or_default]
    pub size: String,
}

#[function_component]
pub Button(Props { primary, size }) -> Html {
    let button_class = if *primary { "primary" } else { "secondary" };
    let size_class = match size.as_str() {
        "small" => "small",
        "large" => "large",
        _ => "medium",
    };

    html! {
        <>
            <button class={classes!("button", button_class, size_class)}>
                {"按钮"}
            </button>
            {styled_jsx!(
                r#"
                .button {
                    font-family: 'Arial', sans-serif;
                    border: none;
                    border-radius: 3px;
                    cursor: pointer;
                    display: inline-block;
                    line-height: 1;
                    transition: all 0.2s;
                }
                
                .button.primary {
                    color: white;
                    background-color: #1ea7fd;
                }
                
                .button.secondary {
                    color: #333;
                    background-color: transparent;
                    box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
                }
                
                .button.small {
                    font-size: 12px;
                    padding: 10px 16px;
                }
                
                .button.medium {
                    font-size: 14px;
                    padding: 11px 20px;
                }
                
                .button.large {
                    font-size: 16px;
                    padding: 12px 24px;
                }
                
                .button:hover {
                    opacity: 0.9;
                }
                "#
            )}
        </>
    }
}

特性

  1. 组件级样式封装:样式与组件紧密绑定,避免全局CSS污染
  2. 自动前缀:自动添加浏览器前缀,确保跨浏览器兼容性
  3. 动态样式:可以根据组件props动态生成样式
  4. 高效编译:通过SWC进行高效编译

文档

更多详细用法请参考官方文档

项目信息

  • 版本:0.97.0
  • 许可证:Apache-2.0
  • 大小:67.1 KiB

1 回复

Rust的CSS-in-JS库styled_jsx使用指南

styled_jsx是一个为Rust项目设计的CSS-in-JS库,它提供了组件级的CSS样式封装方案,让开发者能够在Rust代码中直接编写CSS样式,实现样式与组件的紧密耦合。

主要特性

  • 组件级样式作用域:自动为样式添加唯一标识,避免全局污染
  • CSS-in-JS语法:直接在Rust代码中编写CSS
  • 高性能:编译时处理,运行时零开销
  • 支持Sass类语法:嵌套规则、变量等现代CSS特性

安装方法

Cargo.toml中添加依赖:

[dependencies]
styled_jsx = "0.4"

基本使用方法

1. 定义样式组件

use styled_jsx::styled;

let button = styled! {
    button {
        padding: 8px 16px;
        background: #0070f3;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        
        &:hover {
            background: #0061d5;
        }
    }
};

2. 使用样式组件

use yew::prelude::*;

#[function_component]
fn MyComponent() -> Html {
    html! {
        <div>
            <button class={button}>
                {"点击我"}
            </button>
        </div>
    }
}

高级用法

动态样式

use styled_jsx::styled;

fn get_dynamic_button(primary: bool) -> String {
    styled! {
        button {
            padding: 8px 16px;
            background: ${if primary { "#0070f3" } else { "#eaeaea" }};
            color: ${if primary { "white" } else { "#333" }};
            border: none;
            border-radius: 4px;
        }
    }
}

全局样式

use styled_jsx::global;

global! {
    body {
        margin: 0;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    }
    
    a {
        color: #0070f3;
        text-decoration: none;
    }
}

样式继承

use styled_jsx::styled;

let base_button = styled! {
    button {
        padding: 8px 16px;
        border-radius: 4px;
        cursor: pointer;
    }
};

let primary_button = styled! {
    ${base_button} {
        background: #0070f3;
        color: white;
        
        &:hover {
            background: #0061d5;
        }
    }
};

完整示例代码

下面是一个完整的Yew组件示例,展示了styled_jsx的各种用法:

use yew::prelude::*;
use styled_jsx::{styled, global};

// 定义全局样式
global! {
    body {
        margin: 0;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    }
}

// 基础按钮样式
fn base_button_style() -> String {
    styled! {
        button {
            padding: 10px 20px;
            border-radius: 5px;
            font-size: 1rem;
            cursor: pointer;
            transition: all 0.2s ease;
        }
    }
}

// 主要按钮组件
#[function_component]
fn PrimaryButton() -> Html {
    let style = styled! {
        ${base_button_style()} {
            background: #0070f3;
            color: white;
            border: none;
            
            &:hover {
                background: #0061d5;
            }
        }
    };
    
    html! {
        <button class={style}>
            {"主要按钮"}
        </button>
    }
}

// 次要按钮组件
#[function_component]
fn SecondaryButton() -> Html {
    let style = styled! {
        ${base_button_style()} {
            background: #eaeaea;
            color: #333;
            border: 1px solid #ccc;
            
            &:hover {
                background: #ddd;
            }
        }
    };
    
    html! {
        <button class={style}>
            {"次要按钮"}
        </button>
    }
}

// 带动态样式的卡片组件
#[function_component]
fn CardComponent() -> Html {
    let is_highlighted = true;
    
    let card_style = styled! {
        div {
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            background: ${if is_highlighted { "#fff8e1" } else { "white" }};
            margin-bottom: 20px;
        }
    };
    
    let title_style = styled! {
        h2 {
            color: #333;
            margin-top: 0;
            margin-bottom: 10px;
        }
    };
    
    html! {
        <div class={card_style}>
            <h2 class={title_style}>{"卡片标题"}</h2>
            <p>{"这是一个使用styled_jsx的卡片组件示例"}</p>
            <div style="margin-top: 15px;">
                <PrimaryButton />
                <SecondaryButton />
            </div>
        </div>
    }
}

// 主应用组件
#[function_component]
fn App() -> Html {
    let container_style = styled! {
        div {
            max-width: 800px;
            margin: 0 auto;
            padding: 40px 20px;
        }
    };
    
    html! {
        <div class={container_style}>
            <h1>{"styled_jsx示例应用"}</h1>
            <CardComponent />
        </div>
    }
}

fn main() {
    yew::Renderer::<App>::new().render();
}

构建配置

在项目的build.rs文件中添加以下配置以优化样式输出:

fn main() {
    styled_jsx::configure()
        .minify(true)  // 生产环境压缩CSS
        .write_to_file("static/styles.css")  // 将CSS提取到单独文件
        .setup();
}

注意事项

  1. 样式类名在开发模式下是有意义的名称,在生产模式下会被压缩成短名称
  2. 动态样式在每次渲染时都会生成新的CSS,应谨慎使用
  3. 对于大型项目,建议将基础样式提取到单独的文件中
  4. 样式继承功能可以帮助减少重复代码,提高可维护性
回到顶部