Nami
A powerful, lightweight reactive framework.
Core of our architecture: Signal trait
use ;
Signal describes a reactive value that can be computed and observed. It can generate a new value by get() method.
And it will notify watchers only when its value actually changes.
This trait is implemented by Binding, Computed, and all other reactive types, providing a consistent interface for working with reactive values regardless of their specific implementation.
Computed<T> is a type-erased container that can hold any implementation of the Signal trait, providing a uniform way to work with different kinds of computations.
Binding
Binding<T> is a two-way binding container.
use binding;
// Create a binding with an initial value
let counter = binding;
// Modify the binding
counter.set;
counter.increment; // Now equals 6
// Read the current value
assert_eq!;
Bindings serve as the source of truth for application state and notify observers when their values change. They provide specialized methods for different data types:
Binding<bool>-toggle()for boolean valuesBinding<i32>-increment(),decrement()for integersBinding<Str>-append(),clear()for stringsBinding<Vec<T>>-push(),clear()for vectors
Watchers
Watchers let you react to changes in reactive values:
use ;
let name = binding;
// Watch for changes and execute a callback
let _guard = name.watch;
// This will trigger the watcher
name.set;
What's more, watchers can receive metadata through the Context parameter. This is essential for our reactive animation system.
When working with watchers, it's important to store the returned WatcherGuard. This guard ensures the watcher is properly unregistered when dropped, preventing memory leaks.