#ui-framework #foundation #state #state-management #calculations #sigmut

sigmut-macros

一种旨在作为UI框架基础的州管理框架

2个版本

0.0.2 2024年7月21日
0.0.1 2024年5月30日

#1289 in 过程宏

Download history 128/week @ 2024-05-27 9/week @ 2024-06-03 4/week @ 2024-06-10 80/week @ 2024-07-15 56/week @ 2024-07-22

136 每月下载量
sigmut 中使用

MIT/Apache

18KB
281

sigmut

Crates.io Docs.rs Actions Status

sigmut 是一种旨在作为UI框架基础的州管理框架。

[!WARNING] 警告:此包仍处于非常早期的发展阶段。API将更改。文档较少。

功能

  • 基于信号的API
  • “状态变化”与“状态计算”的分离
  • 易于使用的单线程模型
  • 支持使用 async/await 进行异步操作
  • 无缺陷(不基于过时状态进行不必要的计算)
  • 能够实现更高效的反应原语

基于信号的API

sigmut 中,状态管理是通过以下反应原语进行的

  • State<T>:类似于 Rc<RefCell<T>>,但增加了观察变化的函数。
  • Signal<T>:类似于 Rc<dyn Fn() -> &T>,但增加了观察结果变化的函数。
  • effect:当相关状态发生变化时再次调用的函数。
use sigmut::{Signal, State};

let mut rt = sigmut::core::Runtime::new();

let a = State::new(0);
let b = State::new(1);
let c = Signal::new({
    let a = a.clone();
    let b = b.clone();
    move |sc| a.get(sc) + b.get(sc)
});
let _e = c.effect(|x| println!("{x}"));

rt.update(); // prints "1"

a.set(2, rt.ac());
rt.update(); // prints "3"

a.set(3, rt.ac());
b.set(5, rt.ac());
rt.update(); // prints "8"

状态之间的依赖关系将自动跟踪,当发生变化时将自动触发重新计算。

这种机制是最近的一个趋势,也被其他状态管理库采用,如下所示

“状态变化”与“状态计算”的分离

许多状态管理库通过将状态变化与状态计算分离来简化程序。

Elm中,模型-视图-更新架构将状态变化(更新)与状态计算(视图)分离。

React中,Components and Hooks must be pure的规则禁止在状态计算期间进行状态变化。在React的严格模式下,状态计算将额外调用一次以确保遵循此规则。

SolidJS中,在状态计算期间做出的状态变化将被延迟到状态计算完成

sigmut中,使用SignalContextActionContext将状态变化和状态计算分离。

通过要求执行状态变化或状态计算的功能使用相应的上下文,明确区分了状态变化和状态计算,编译器可以强制实施这种分离。

"状态变化与状态计算的分离"通过在状态计算期间将状态视为不可变来简化程序,这与Rust的所有权概念类似。内部,sigmut使用RefCell,但这种相似性有助于避免状态计算期间的BorrowError。如果您正在使用许多Rc<RefCell<T>>,切换到sigmut可以导致更健壮的程序,并且出现BorrowError的情况更少。

易于使用的单线程模型

sigmut采用单线程模型的原因如下

  • 简单且易于处理
  • 没有死锁的风险
  • 不需要同步,允许即时检索当前值
  • async/await的互操作性,使多线程的优势得以体现
  • 能够实现无故障(没有基于过时状态的无效计算)

支持使用 async/await 进行异步操作

sigmutasync/await集成,允许异步操作被视为同步的Poll<T>状态。这使得与异步运行时(如tokio)的互操作性成为可能。

有关更多详细信息,请参阅名称包含asyncfuturestream的函数和类型。

无缺陷(不基于过时状态进行不必要的计算)

一些状态管理库在状态计算期间使用过时的缓存,这可能导致意外的结果。虽然这些意外结果会被迅速重新计算,不期望的计算结果会被丢弃,但这仍然可能导致问题,包括潜在的恐慌。因此,仅仅因为重新计算而发生,并不意味着问题已经完全解决。

sigmut 中,缓存通过将它们分类为三种类型进行管理:clean(干净)、dirty(脏)和maybe dirty(可能脏)。通过持续准确地检查这些缓存的有效性,sigmut 避免了在状态计算中使用过时缓存相关的问题。

能够实现更高效的反应原语

sigmut 包含一个低级模块,sigmut::core,它仅处理状态变化通知。通过使用此模块,您可以在特定条件下实现更高效的反应式原语。

此实现的示例是 SignalVec<T>SignalVec<T>Signal<Vec<T>> 类似,但它允许您获取自上次访问以来的更改历史,从而实现更有效的处理。

许可证

本项目采用 Apache-2.0/MIT 双重许可。有关详细信息,请参阅两个 LICENSE-* 文件。

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在作品中的任何贡献,将如上所述双重许可,不附加任何额外条款或条件。

依赖关系

~2.3–4MB
~69K SLoC