网站 | 文档 | Docs.rs | 在线试用 | Discord
你可以在awesome-leptos
找到一系列有用的库和示例项目。
main
分支目前正在为0.7版本的发布进行重大更改。如需稳定版本,请使用v0.6.13标签
Leptos
use leptos::*;
#[component]
pub fn SimpleCounter(initial_value: i32) -> impl IntoView {
// 创建一个带有初始值的响应式信号
let (value, set_value) = create_signal(initial_value);
// 为按钮创建事件处理器
// 注意`value`和`set_value`是`Copy`的,所以很容易将它们移入闭包
let clear = move |_| set_value(0);
let decrement = move |_| set_value.update(|value| *value -= 1);
let increment = move |_| set_value.update(|value| *value += 1);
// 使用声明式的`view!`宏创建用户界面
view! {
<div>
<button on:click=clear>清零</button>
<button on:click=decrement>-1</button>
// 文本节点可以加引号也可以不加
<span>"值:" {value} "!"</span>
<button on:click=increment>+1</button>
</div>
}
}
// 我们还支持构建器语法,而不是类似JSX的`view`宏
#[component]
pub fn SimpleCounterWithBuilder(initial_value: i32) -> impl IntoView {
use leptos::html::*;
let (value, set_value) = create_signal(initial_value);
let clear = move |_| set_value(0);
let decrement = move |_| set_value.update(|value| *value -= 1);
let increment = move |_| set_value.update(|value| *value += 1);
// 上面的`view`宏会展开成这种构建器语法
div().child((
button().on(ev::click, clear).child("清零"),
button().on(ev::click, decrement).child("-1"),
span().child(("值:", value, "!")),
button().on(ev::click, increment).child("+1")
))
}
// 易于与Trunk(trunkrs.dev)或简单的wasm-bindgen设置一起使用
pub fn main() {
mount_to_body(|| view! {
<SimpleCounter initial_value=3 />
})
}
关于框架
Leptos是一个全栈、同构的Rust Web框架,利用细粒度响应式来构建声明式用户界面。
这意味着什么?
- 全栈:Leptos可用于构建在浏览器中运行(客户端渲染)、在服务器上运行(服务器端渲染)或通过在服务器上渲染HTML然后在浏览器中添加交互性(服务器端渲染与水合)的应用程序。这包括支持数据(
Resource
)和HTML(<Suspense/>
组件的顺序或乱序流式传输)的HTTP流式传输。 - 同构:Leptos提供了编写同构服务器函数的原语,即可以在客户端或服务器上以"相同形式"调用但只在服务器上运行的函数。这意味着你可以将服务器专用逻辑(数据库请求、身份验证等)与将使用它的客户端组件一起编写,并像在浏览器中运行一样调用服务器函数,而无需创建和维护单独的REST或其他API。
- Web:Leptos建立在Web平台和Web标准之上。路由器旨在使用Web基础(如链接和表单)并在此基础上构建,而不是试图替代它们。
- 框架:Leptos提供了构建现代Web应用所需的大部分内容:一个响应式系统、模板库和一个在服务器和客户端都能工作的路由器。
- 细粒度响应式:整个框架都建立在响应式原语之上。这允许极其高性能的代码,开销最小:当响应式信号的值发生变化时,它可以更新单个文本节点、切换单个类或从DOM中移除一个元素,而无需运行任何其他代码。(因此,没有虚拟DOM开销!)
- 声明式:告诉Leptos你希望页面看起来是什么样子,让框架告诉浏览器如何实现它。
了解更多
以下是一些学习更多关于Leptos的资源:
nightly
说明
大多数示例假设你正在使用Rust的nightly
版本和Leptos的nightly
特性。要使用nightly
Rust,你可以全局设置工具链或在每个项目的基础上设置。
要将nightly
设置为所有项目的默认工具链(并添加编译Rust到WebAssembly的能力,如果你还没有的话):
rustup toolchain install nightly
rustup default nightly
rustup target add wasm32-unknown-unknown
如果你只想在Leptos项目中使用nightly
,请添加一个rust-toolchain.toml
文件,内容如下:
[toolchain]
channel = "nightly"
targets = ["wasm32-unknown-unknown"]
nightly
特性启用了访问和设置信号的函数调用语法,而不是.get()
和.set()
。这导致了一个一致的心智模型,即访问任何类型的响应式值(信号、备忘录或派生信号)总是表示为函数调用。这只有在使用nightly Rust和nightly
特性时才可能。
cargo-leptos
cargo-leptos
是一个构建工具,旨在让构建同时在客户端和服务器上运行的应用变得容易,并实现无缝集成。目前开始真正的Leptos项目的最佳方式是使用cargo-leptos
和我们的Actix或Axum启动模板。
cargo install cargo-leptos
cargo leptos new --git https://github.com/leptos-rs/start
cd [你的项目名称]
cargo leptos watch
在浏览器中打开http://localhost:3000/。
常见问题
名字是怎么回事?
Leptos(λεπτός)是一个古希腊词,意思是"薄的、轻的、精炼的、细粒度的"。对我这个古典学者而非狗主人来说,它让人联想到驱动框架的轻量级响应式系统。我后来才知道,同一个词是医学术语"钩端螺旋体病"的词根,这是一种影响人类和动物的血液感染...抱歉。在创建这个框架的过程中没有伤害任何狗。
它可以用于生产环境吗?
人们通常用这个问题表达三种意思。
- **API是稳定的吗?**也就是说,我是否需要从Leptos 0.1到0.2到0.3到0.4完全重写我的整个应用,还是我现在就可以编写它并在新版本发布时受益于新功能和更新?
API基本上已经稳定下来。我们正在添加新功能,但我们对类型系统和模式的现状非常满意。就架构而言,我不认为你需要对代码进行重大的破坏性改变来适应未来的版本。
-
有bug吗? 是的,我确信存在一些问题。从我们的问题跟踪器状态随时间的变化可以看出,bug并不是很多,而且通常能够很快得到解决。但是,确实可能会有一些时刻,你遇到的问题需要在框架层面进行修复,这可能不会立即解决。
-
我是消费者还是贡献者?
这可能是最重要的一点:"生产就绪"意味着对库的一种特定定位:你基本上可以使用它,而不需要对其内部结构有特别了解或具备贡献能力。每个人在其技术栈中某个层面都有这样的情况:例如,我(@gbj)目前没有能力或知识去为像wasm-bindgen
这样的项目做贡献:我只是依赖它来工作。
社区中有几个人现在正在工作中的内部应用中使用Leptos,他们也成为了重要的贡献者。我认为这是目前正确的生产使用水平。可能会有你需要的功能还未实现,你可能最终会去构建它们!但对于内部应用来说,如果你愿意在使用过程中构建和贡献缺失的部分,这个框架现在绝对是可用的。
我可以用它来开发原生GUI吗?
当然可以!显然,view
宏是用来生成DOM节点的,但你可以使用响应式系统来驱动任何使用与DOM类似的面向对象、基于事件回调的框架的原生GUI工具包。原理是相同的:
- 使用信号、派生信号和备忘录来创建你的响应式系统
- 创建GUI小部件
- 使用事件监听器来更新信号
- 创建效果来更新UI
我制作了一个非常简单的GTK示例,你可以看看我的意思。
正在为0.7版本开发的新渲染方法支持"通用渲染",即它可以使用任何支持一小组6-8个函数的渲染库。(这旨在作为典型的保留模式、面向对象风格GUI工具包如DOM、GTK等的一个层。)这个未来的渲染工作将允许以更类似于Web框架使用的声明式方法来创建原生UI。
这与Yew有什么不同?
Yew是最常用的Rust Web UI开发库,但Yew和Leptos在理念、方法和性能上有几个不同之处。
- 虚拟DOM vs. 细粒度: Yew建立在虚拟DOM(VDOM)模型上:状态变化导致组件重新渲染,生成新的虚拟DOM树。Yew将其与之前的VDOM进行对比,并将这些变化应用到实际的DOM上。每当状态发生变化时,组件函数就会重新运行。Leptos采用了完全不同的方法。组件只运行一次,创建(并返回)实际的DOM节点,并设置一个响应式系统来更新这些DOM节点。
- 性能: 这在性能上有巨大的影响:Leptos在创建和更新UI方面都比Yew快得多。
- 服务器集成: Yew创建于浏览器渲染的单页应用(SPA)是主导范式的时代。虽然Leptos支持客户端渲染,但它还关注通过服务器函数和多种HTML服务模式(包括无序流式传输)与应用程序的服务器端集成。
这与Dioxus有什么不同?
像Leptos一样,Dioxus也是一个使用Web技术构建UI的框架。然而,在方法和功能上存在显著差异。
- 虚拟DOM vs. 细粒度: 虽然Dioxus有一个高性能的虚拟DOM(VDOM),但它仍然使用粗粒度/组件范围的响应式:改变一个状态值会重新运行组件函数,并将旧UI与新UI进行对比。Leptos组件使用不同的心智模型,创建(并返回)实际的DOM节点,并设置一个响应式系统来更新这些DOM节点。
- Web vs. 桌面优先: Dioxus在其全栈模式中使用了Leptos服务器函数,但不具有相同的基于
<Suspense>
的支持,比如流式HTML渲染,也不共享同样的全面Web性能关注点。Leptos倾向于优先考虑全面的Web性能(流式HTML渲染、更小的WASM二进制大小等),而Dioxus在构建桌面应用时提供了无与伦比的体验,因为你的应用逻辑作为原生Rust二进制运行。
这与Sycamore有什么不同?
Sycamore和Leptos都深受SolidJS的影响。目前,Leptos拥有更大的社区和生态系统,并且更加活跃地开发。其他差异:
- 模板DSL: Sycamore为其视图使用自定义模板语言,而Leptos使用类似JSX的模板格式。
'static
信号: Leptos的主要创新之一是创建了Copy + 'static
信号,这具有出色的人体工程学。Sycamore正在采用相同的模式,但尚未发布。- Perseus vs. 服务器函数: Perseus元框架提供了一种固定的方式来构建包含服务器功能的Sycamore应用。Leptos则在框架核心中提供了诸如服务器函数之类的原语。