请注意:该框架正在积极开发中。目前,我将其保持在 0.0.x 版本的循环中,以表明它甚至还没有为 0.1.0 做好准备。正在对文档和功能进行积极的工作,API 不一定被认为是稳定的。同时,它不仅仅是一个玩具项目或概念验证,我正在积极将其用于我自己的应用程序开发。
use leptos::*;
#[component]
pub fn SimpleCounter(cx: Scope, initial_value: i32) -> Element {
// create a reactive signal with the initial value
let (value, set_value) = create_signal(cx, initial_value);
// create event handlers for our buttons
// note that `value` and `set_value` are `Copy`, so it's super easy to move them into closures
let clear = move |_| set_value(0);
let decrement = move |_| set_value.update(|value| *value -= 1);
let increment = move |_| set_value.update(|value| *value += 1);
// this JSX is compiled to an HTML template string for performance
view! {
cx,
<div>
<button on:click=clear>"Clear"</button>
<button on:click=decrement>"-1"</button>
<span>"Value: " {move || value().to_string()} "!"</span>
<button on:click=increment>"+1"</button>
</div>
}
}
// Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setup
pub fn main() {
mount_to_body(|cx| view! { cx, <SimpleCounter initial_value=3 /> })
}
Leptos 是一个全栈、同构的 Rust Web 框架,利用细粒度的 React 性来构建声明式用户界面。
Resource
<Suspense/>
以下是一些了解有关乐浦的更多信息的资源:
nightly注意
大多数示例都假设你正在使用 Rust。如果你处于稳定状态,请注意以下事项:
nightly
"stable"
Cargo.toml
leptos = { version = "0.0", features = ["stable"] }
nightly启用用于访问和设置信号的函数调用语法。如果使用 ,则只需调用 、 或手动操作。查看
计数器稳定示例
,了解正确 API 的示例。stable
.get()
.set()
.update()
基准
服务器端呈现我创建了一个基准测试,将Leptos在服务器上的HTML渲染与Tera,Yew和Sycamore进行了比较。你可以在此处找到基准测试,并使用 .Leptos 渲染 HTML 的速度大致与 Tera 一样快,并且随着模板变大而扩展良好。它比类似框架完成的服务器端HTML渲染要快得多。
cargo bench
点击显示结果
ns/iter
泰拉
乐浦
紫杉
悬铃木
3 计数器
3,454
5,666
34,984
32,412
TodoMVC (no todos)
2,396
5,561
38,725
68,749
TodoMVC (1000 todos)
3,829,447
3,077,907
5,125,639
19,448,900
平均
1.08
1.65
6.25
9.36
客户端呈现测试前端 Web 框架原始渲染性能的黄金标准是 js-framework-benchmark。官方结果将Leptos列为最快的Rust / Wasm框架,比SolidJS略慢,比流行的JS框架(如Svelte,Preact和React)快得多。
常见问题
我可以将其用于本机 GUI 吗?确定!显然,宏用于生成 DOM 节点,但你可以使用响应式系统来驱动任何使用与 DOM 相同类型的面向对象、基于事件回调的框架的 GUI 工具包。原理是相同的:
view
- 使用信号、派生信号和备忘录来创建 React 式系统
- 创建图形用户界面小部件
- 使用事件侦听器更新信号
- 创建效果以更新 UI
我整理了一个非常简单的 GTK 示例,以便你了解我的意思。
这与红豆杉/红豆杉有何不同?从表面上看,这些库可能看起来很相似。当然,Yew 是用于 Web UI 开发的最成熟的 Rust 库,并且拥有庞大的生态系统。Dioxus 在很多方面都很相似,都深受 React 的启发。以下是乐浦和这些框架之间的一些概念差异:
-
VDOM 与细粒度:Yew 建立在虚拟 DOM (VDOM) 模型之上:状态更改会导致组件重新渲染,从而生成新的虚拟 DOM 树。Yew 将其与以前的 VDOM 进行了区分,并将这些补丁应用于实际的 DOM。 每当状态更改时,组件函数都会重新运行。乐浦采取了完全不同的方法。组件运行一次,创建(并返回)实际的 DOM 节点,并设置一个 React 式系统来更新这些 DOM 节点。
-
性能:这具有巨大的性能影响:Leptos 在创建和更新 UI 方面都比 Yew 快得多。
-
心智模型:采用细粒度的 React 性也倾向于简化心智模型。没有令人惊讶的组件重新渲染,因为没有重新渲染。你的应用可以根据对你的应用有意义的内容划分为多个组件,因为它们对性能没有影响。
这与梧桐树有何不同?从概念上讲,这两个框架非常相似:因为两者都建立在细粒度的 React 性之上,所以大多数应用程序最终在两者之间看起来非常相似,Sycamore或Leptos应用程序看起来都很像SolidJS应用程序,就像Yew或Dioxus看起来很像React一样。
有一些实际差异会产生显着差异:
-
成熟:Sycamore显然是一个更成熟,更稳定的库,具有更大的生态系统。
-
模板:Leptos 使用类似 JSX 的模板格式(基于 syn-rsx 构建)作为其宏。Sycamore提供了自己的模板DSL或构建器语法的选择。
view
-
模板节点克隆:Leptos 的宏编译为一个静态的 HTML 字符串和一组如何分配其 React 式值的指令。这意味着在运行时,Leptos 可以克隆节点,而不是调用来创建 DOM 节点。这是一种明显更快的渲染组件的方法。
view
<template>
document.createElement()
-
读写隔离:Leptos 和 Solid 一样,鼓励信号获取器和设置器之间的读写隔离,因此你最终可以使用元组访问信号,例如(如果你愿意,或者如果你的 API 更方便,你可以使用
create_rw_signal 来提供统一的读/写信号。
let (count, set_count) = create_signal(cx, 0);
-
信号是函数:在 Leptos 中,你可以调用一个信号来访问它,而不是调用一个特定的方法(所以,而不是 ) 这创造了一个更一致的心智模型:访问一个 React 值总是调用一个函数的问题。例如:
count()
count.get()
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
-
信号和示波器是
“静态的”:
Leptos 和 Sycamore 都减轻了闭包(特别是事件侦听器)中移动信号的痛苦,以避免 Rust UI 代码中非常熟悉的。Sycamore 通过使用凹凸分配将其信号的生命周期与其作用域联系起来来实现这一点:由于引用是 ,可以移动到闭包中。Leptos 通过使用竞技场分配和传递索引来实现这一点:像 、 这样的类型实际上是将索引包装到竞技场中。这意味着示波器和信号都在乐浦中,这意味着它们可以很容易地移动到闭包中,而不会增加生命周期的复杂性。Copy
{ let count = count.clone(); move |_| ... }
Copy
&'a Signal<T>
ReadSignal<T>
WriteSignal<T>
Memo<T>
Copy
'static