Files
Glint-Runtime/docs/ru/modules/03-reactive.md

3.8 KiB
Raw Blame History

Модуль реактивности: src/interpreter/reactive.rs

Система отслеживания зависимостей между переменными и элементами VDOM. Позволяет пересчитывать только изменившиеся элементы (Phase 3).


ElementId(u32)

Уникальный идентификатор элемента в VDOM-дереве. Раздаётся ReactiveTracker::alloc_id() во время загрузки шаблона.

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementId(pub u32);

Используется как:

  • Ключ в dirty_set: HashSet<ElementId>
  • Ключ в dependencies: HashMap<ElementId, HashSet<String>>
  • Поле в Element::element_id (связь VDOM → tracker)
  • Источник для iced::widget::Id (Phase 9.2: format!("ti:{}", id.0))
  • Источник для scrollable_id (el.element_id.0 as u64)

ReactiveTracker

Граф зависимостей: переменная → список элементов, которые её используют.

pub struct ReactiveTracker {
    subscribers: HashMap<String, HashSet<ElementId>>,
    dependencies: HashMap<ElementId, HashSet<String>>,
    dirty_set: HashSet<ElementId>,
    next_id: u32,
}

Поля:

  • subscribers — для каждой переменной: какие ElementId от неё зависят
  • dependencies — для каждого элемента: от каких переменных он зависит (обратная связь)
  • dirty_set — элементы, которые нужно пересчитать в следующем фрейме
  • next_id — счётчик для alloc_id()

Методы

Метод Описание
new() Пустой tracker
alloc_id() -> ElementId Выделить новый ID, увеличить счётчик
add_dependency(element, var_name) Зарегистрировать зависимость
scan_value(element, value) Сканировать строку на $var и добавить зависимости
on_variable_changed(name) Пометить все зависимые элементы как dirty
take_dirty_set() -> HashSet<ElementId> Забрать dirty_set и очистить
is_dirty(id) -> bool Проверить, помечен ли элемент
reset() Очистить все данные

scan_value()

Парсит строку в поиске $var_name паттернов:

"Hello $name, you are $age years old"
// → add_dependency(element, "name")
// → add_dependency(element, "age")

Используется во время загрузки шаблона для каждой properties строки, содержащей $. В результате каждый элемент знает, от каких переменных зависит.

Цикл обновления

Событие → update() → on_variable_changed("var")
  → dirty_set = {element_A, element_B, ...}
  → take_dirty_set() → evaluate_vdom_incr(roots, &dirty_set)
    → для элементов в dirty_set: пересчитать
    → для остальных: вернуть как есть

Тесты

Тест Что проверяет
test_basic_dependency_tracking Два элемента, две переменные, правильность dirty_set
test_scan_value Парсинг $var из строки
test_scan_no_vars Строка без $ не создаёт зависимостей
test_take_dirty_set take_dirty_set() очищает внутренний set
test_reset reset() очищает всё