# Модуль реактивности: `src/interpreter/reactive.rs` Система отслеживания зависимостей между переменными и элементами VDOM. Позволяет пересчитывать только изменившиеся элементы (Phase 3). --- ## `ElementId(u32)` Уникальный идентификатор элемента в VDOM-дереве. Раздаётся `ReactiveTracker::alloc_id()` во время загрузки шаблона. ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ElementId(pub u32); ``` **Используется как:** - Ключ в `dirty_set: HashSet` - Ключ в `dependencies: HashMap>` - Поле в `Element::element_id` (связь VDOM → tracker) - Источник для `iced::widget::Id` (Phase 9.2: `format!("ti:{}", id.0)`) - Источник для scrollable_id (`el.element_id.0 as u64`) --- ## `ReactiveTracker` Граф зависимостей: переменная → список элементов, которые её используют. ```rust pub struct ReactiveTracker { subscribers: HashMap>, dependencies: HashMap>, dirty_set: HashSet, 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` | Забрать dirty_set и очистить | | `is_dirty(id) -> bool` | Проверить, помечен ли элемент | | `reset()` | Очистить все данные | ### scan_value() Парсит строку в поиске `$var_name` паттернов: ```rust "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()` очищает всё |