9 个版本 (稳定)
2.2.0 | 2022年6月9日 |
---|---|
2.0.1 | 2021年11月20日 |
2.0.0 | 2021年2月8日 |
1.1.0 | 2019年12月23日 |
0.1.0 | 2018年3月17日 |
#374 在 算法 中
每月97次下载
用于 5 个crate
145KB
2.5K SLoC
flo_binding
,一个数据驱动绑定库
flo_binding
提供创建 '数据绑定' 的方式,这是在应用程序的不同部分之间存储和共享状态的一种方式。围绕这些数据结构设计的应用程序有时被称为 '响应式' 应用程序。
可以使用 bind()
函数创建基本绑定
let binding = bind(1);
可以通过调用 set()
来更新,并使用 get()
来检索
let value = binding.get(); // == 1
binding.set(2);
let value = binding.get(); // == 2
克隆绑定将共享状态
let another_binding = binding.clone();
another_binding.set(3);
let value = another_binding.get(); // == 3
let value = binding.get(); // Also == 3
有两种主要方式可以在绑定更改时收到通知。当绑定自上次读取以来已更改时,when_changed()
函数提供调用函数的方式,而 follow()
函数将返回绑定最近附加的值的 Stream。流式方法是最灵活的。
let binding = bind(1);
let mut event_lifetime = binding.when_changed(notify(|| { println!("Binding changed"); }));
let mut binding_stream = follow(binding.clone());
let value = binding_stream.next().await; // == 1
binding.set(2); // Prints 'Binding changed'
binding.set(3); // Changed flag is set, so prints nothing
let value = binding.get(); // == 3
binding.set(4); // Prints 'Binding changed' again
let value = binding_stream.next().await; // == 4 (stream does not return intermediate values)
let value = binding_stream.next().await; // Blocks until something elsewhere updates the binding
event_lifetime.done();
binding.set(5); // Prints nothing as the 'when_changed' event has been deregistered
follow()
的逆操作是 bind_stream()
,它创建一个与从流接收到的最后一个值保持更新的绑定
let binding = bind(1);
let binding_from_stream = bind_stream(follow(binding.clone()), 1, |_old_value, new_value| new_value);
let value = binding.get(); // == 1
let value = binding_from_stream.get(); // == 1
binding.set(2);
let value = binding_from_stream.get(); // == 2
这样的流绑定是只读的,但将任何状态值流转换为表示静态状态的值的好方法。它实现了所有其他绑定操作。
另一种重要的绑定类型是 computed()
绑定,它可以使创建一个从其他绑定中派生值的绑定成为可能。计算绑定会自动监视任何被捕获的绑定以检测变化,因此它们可以像任何其他绑定一样被 follow
或 when_change
。
let binding = bind(1);
let binding_copy = binding.clone();
let one_more = computed(move || binding_copy.get() + 1);
let mut event_lifetime = one_more.when_changed(notify(|| println!("Computed binding changed")));
let value = one_more.get(); // == 2 (1 + 1)
binding.set(2); // Prints 'Computed binding changed'
binding.set(3); // Computed binding has not been read since the last notification so prints nothing
let value = one_more.get(); // == 4 (3 + 1)
对于数据集合,flo_binding
使用了“绳绑定”的概念。绳数据类型由 flo_rope
crate 提供。这些绑定在流式传输时发送差异而不是它们的完整状态,并在内部通过一种可以高效执行删除和插入操作的数据结构表示。与传统的绳概念不同,它们不仅限于编辑字符串,还可以使用属性注释其内容,这使得它们适合表示任何类型的序列,或带有样式信息的富文本序列。
let mutable_rope = RopeBindingMut::<usize, ()>::new();
let rope_copy = RopeBinding::from_stream(mutable_rope.follow_changes());
let mut rope_stream = rope_copy.follow_changes();
mutable_rope.replace(0..0, vec![1, 2, 3, 4]);
let next = rope_stream.next().await; // == RopeAction::Replace(0..0, vec![1,2,3,4]))
let rope_len = rope_copy.len(); // == 4
let rope_content = rope_copy.read_cells(0..4).collect::<Vec<_>>(); // == vec![1, 2, 3, 4]
flo_rope
库提供了一些额外功能——例如,通过在变化的序列上使用差异算法而不是仅仅报告到达的变化,来创建绳的 RopeAction
。
配套库
除了 flo_rope
之外,desync
crate 提供了一种新颖的异步代码方法,包括与 follow()
函数的流式更新协同工作的管道操作。
flo_stream
提供了一个 pubsub 系统,它提供了通过流分发状态的更灵活的方法。
flo_scene
是一个运行时,用于构建由相互交换消息的实体组成的复杂系统。它使用 flo_binding
作为交换状态信息的便捷方式。
FlowBetween
是一个矢量和平面动画编辑器,它使用 flo_binding
来表示其用户界面。
依赖项
~0–255KB