leptos基础组件分析
先给出代码
use leptos::prelude::*;
// #[component]宏将一个函数标记为 可重用的组件a function as a reusable component
#[component]
fn App() -> impl IntoView {
// 创建一个反应式的信号,并得到 一对 getter, setter
let (count, set_count) = signal(0);
view! {
<button
// 当 click 事件发生时,执行这个闭包
// move表示:把闭包中使用到的外部变量“按值捕获”进闭包内部。
on:click=move |_| *set_count.write() += 1
>
"Click me: "
{count}
</button>
<p>
<strong>"Reactive: "</strong>
{move || count.get()}
</p>
<p>
<strong>"Reactive shorthand: "</strong>
{count}
</p>
<p>
<strong>"Not reactive: "</strong>
// 注意:下面这种写法不是反应式的,只是简单地一次性地得到count的值
{count.get()}
</p>
}
}
fn main() {
leptos::mount::mount_to_body(App)
}
count.get() 会克隆 count的值
set_count.set() 会覆盖改写 count的值
请看
https://docs.rs/leptos/latest/leptos/reactive/signal/struct.ReadSignal.html
https://docs.rs/leptos/latest/leptos/reactive/signal/struct.WriteSignal.html
注意:
move |_| *set_count.write() += 1
相当于
move |event: web_sys::MouseEvent| {
*set_count.write() += 1
}
Leptos 会自动把浏览器的 click 事件对象传进来,但我们没用到 event.
_ 表示 忽略这个参数
更重要的是, set_count.write() 中的 是解引用谁
set_count.write() 返回 WriteSignalGuard
本质类似于 RwLockWriteGuard
它实现了 DerefMut
也就是说 write() 返回一个“可变借用的 guard”
set_count.write() 等价于 (set_count.write())
也就是, 对 write() 返回的 guard 进行解引用
不是对 set_count 解引用。
上面的代码,完全展开,应该是
on:click = move |_: web_sys::MouseEvent| {
let mut value_ref: &mut i32 = &mut *set_count.write();
*value_ref += 1;
}
write() 和 update()的 区别与联系
write() 是用来 获取可变引用的, 返回值是 WriteSignalGuard
使用 *guard 解引用后 修改
update(f) 是 原子修改, 返回值是(), 传入闭包 进行修改。
set_count.update(|value| {
*value += 1;
});
等价于
{
let mut guard = set_count.write();
f(&mut *guard);
}
其中, f就是上面的闭包
也就是说, update() 是 write() 的语法封装
与 set() 的关系
还有一个 set_count.set(5);
它等价于 set_count.update(|v| *v = 5);