You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> :bulb: Совет: Обратите внимание, что мы сознательно не включили сюда функции `addTodo()` и `removeTodo(todo)`. Отделение данных от функций, которые их изменяют, часто помогает упростить архитектуру приложения. Для получения более подробной информации ознакомьтесь со статьёй [дизайн, ориентированный на данные](https://habr.com/ru/articles/321106/).
252
+
> :bulb: Совет: Обратите внимание, что мы сознательно не включили сюда функции `addTodo()` и `removeTodo(todo)`. Отделение данных от функций, которые их изменяют, часто помогает упростить архитектуру приложения. Для получения более подробной информации ознакомьтесь со статьёй [дизайн, ориентированный на данные](https://www.dataorienteddesign.com/dodbook/).
253
253
>
254
254
> Теперь мы можем передать состояние нашего приложения todo в качестве параметра при рендеринге:
Подробнее о том, как использовать модели в ваших компонентах, и полная справочная информация по API — см. [API моделей](#createmodelfactory) в разделе API ниже.
545
545
546
+
#### Ключевые возможности
547
+
548
+
-**Аргументы фабрики**: Фабричные функции могут принимать аргументы для инициализации, что делает модели повторно используемыми с разными конфигурациями.
549
+
-**Автоматическая пакетная обработка**: Все методы, возвращаемые из фабрики, автоматически оборачиваются как действия, поэтому обновления состояния внутри них группируются в пакет и не отслеживаются.
550
+
-**Автоматическая очистка эффектов**: Эффекты, созданные при построении модели, захватываются и автоматически удаляются при уничтожении модели через `Symbol.dispose`.
551
+
-**Компонуемые модели**: Модели естественно компонуются — эффекты из вложенных моделей захватываются родительской и удаляются вместе с ней при уничтожении родителя.
552
+
553
+
#### Композиция моделей
554
+
555
+
Модели можно вкладывать друг в друга. При уничтожении родительской модели все эффекты из вложенных моделей автоматически очищаются:
556
+
557
+
```js
558
+
constTodoItemModel=createModel((text) => {
559
+
constcompleted=signal(false);
560
+
561
+
return {
562
+
text,
563
+
completed,
564
+
toggle() {
565
+
completed.value=!completed.value;
566
+
}
567
+
};
568
+
});
569
+
570
+
constTodoListModel=createModel(() => {
571
+
constitems=signal([]);
572
+
573
+
return {
574
+
items,
575
+
addTodo(text) {
576
+
consttodo=newTodoItemModel(text);
577
+
items.value= [...items.value, todo];
578
+
},
579
+
removeTodo(todo) {
580
+
items.value=items.value.filter(t=> t !== todo);
581
+
todo[Symbol.dispose]();
582
+
}
583
+
};
584
+
});
585
+
586
+
consttodoList=newTodoListModel();
587
+
todoList.addTodo('Купить продукты');
588
+
todoList.addTodo('Выгулять собаку');
589
+
590
+
// Уничтожение родительской модели также очищает все эффекты вложенных моделей
591
+
todoList[Symbol.dispose]();
592
+
```
593
+
594
+
### Рекомендуемые паттерны
595
+
596
+
#### Явный паттерн ReadonlySignal
597
+
598
+
Для лучшей инкапсуляции объявляйте интерфейс вашей модели явно и используйте `ReadonlySignal` для сигналов, которые должны изменяться только через экшены:
counter.count.value=10; // Ошибка TypeScript: Cannot assign to 'value'
629
+
```
630
+
631
+
#### Пользовательская логика уничтожения
632
+
633
+
Если вашей модели требуется пользовательская логика очистки, не связанная с сигналами (например, закрытие WebSocket-соединений), используйте эффект без зависимостей, который возвращает функцию очистки:
634
+
635
+
```js
636
+
constWebSocketModel=createModel((url) => {
637
+
constmessages=signal([]);
638
+
constws=newWebSocket(url);
639
+
640
+
ws.onmessage= (e) => {
641
+
messages.value= [...messages.value, e.data];
642
+
};
643
+
644
+
// Этот эффект выполняется один раз; его очистка запускается при уничтожении
Этот паттерн аналогичен `useEffect(() => { return cleanup }, [])` в React и гарантирует, что очистка происходит автоматически при композиции моделей — родительским моделям не нужно знать о функциях уничтожения вложенных моделей.
667
+
546
668
## API
547
669
548
670
В этом разделе представлен обзор API сигналов. Он призван стать кратким справочником для людей, которые уже знают, как использовать сигналы, и нуждаются в напоминании о том, что доступно.
-**Аргументы фабрики**: Фабричные функции могут принимать аргументы для инициализации, что делает модели повторно используемыми с разными конфигурациями.
692
-
-**Автоматическая пакетная обработка**: Все методы, возвращаемые из фабрики, автоматически оборачиваются как действия, поэтому обновления состояния внутри них группируются в пакет и не отслеживаются.
693
-
-**Автоматическая очистка эффектов**: Эффекты, созданные при построении модели, захватываются и автоматически удаляются при уничтожении модели через `Symbol.dispose`.
694
-
-**Компонуемые модели**: Модели естественно компонуются — эффекты из вложенных моделей захватываются родительской и удаляются вместе с ней при уничтожении родителя.
695
-
696
-
#### Композиция моделей
697
-
698
-
Модели можно вкладывать друг в друга. При уничтожении родительской модели все эффекты из вложенных моделей автоматически очищаются:
699
-
700
-
```js
701
-
constTodoItemModel=createModel((text) => {
702
-
constcompleted=signal(false);
703
-
704
-
return {
705
-
text,
706
-
completed,
707
-
toggle() {
708
-
completed.value=!completed.value;
709
-
}
710
-
};
711
-
});
712
-
713
-
constTodoListModel=createModel(() => {
714
-
constitems=signal([]);
715
-
716
-
return {
717
-
items,
718
-
addTodo(text) {
719
-
consttodo=newTodoItemModel(text);
720
-
items.value= [...items.value, todo];
721
-
},
722
-
removeTodo(todo) {
723
-
items.value=items.value.filter(t=> t !== todo);
724
-
todo[Symbol.dispose]();
725
-
}
726
-
};
727
-
});
728
-
729
-
consttodoList=newTodoListModel();
730
-
todoList.addTodo('Купить продукты');
731
-
todoList.addTodo('Выгулять собаку');
732
-
733
-
// Уничтожение родительской модели также очищает все эффекты вложенных моделей
734
-
todoList[Symbol.dispose]();
735
-
```
736
-
737
811
### action(fn)
738
812
739
813
Функция `action(fn)` оборачивает функцию для выполнения в пакетном и неотслеживаемом контексте. Это полезно, когда нужно создать самостоятельные действия вне модели:
@@ -798,80 +872,6 @@ function Counter({ initialValue }) {
798
872
}
799
873
```
800
874
801
-
### Рекомендуемые паттерны
802
-
803
-
#### Явный паттерн ReadonlySignal
804
-
805
-
Для лучшей инкапсуляции объявляйте интерфейс вашей модели явно и используйте `ReadonlySignal` для сигналов, которые должны изменяться только через экшены:
counter.count.value=10; // Ошибка TypeScript: Cannot assign to 'value'
836
-
```
837
-
838
-
#### Пользовательская логика уничтожения
839
-
840
-
Если вашей модели требуется пользовательская логика очистки, не связанная с сигналами (например, закрытие WebSocket-соединений), используйте эффект без зависимостей, который возвращает функцию очистки:
841
-
842
-
```js
843
-
constWebSocketModel=createModel((url) => {
844
-
constmessages=signal([]);
845
-
constws=newWebSocket(url);
846
-
847
-
ws.onmessage= (e) => {
848
-
messages.value= [...messages.value, e.data];
849
-
};
850
-
851
-
// Этот эффект выполняется один раз; его очистка запускается при уничтожении
Этот паттерн аналогичен `useEffect(() => { return cleanup }, [])` в React и гарантирует, что очистка происходит автоматически при композиции моделей — родительским моделям не нужно знать о функциях уничтожения вложенных моделей.
874
-
875
875
## Вспомогательные компоненты и хуки
876
876
877
877
Начиная с версии v2.1.0, пакет `@preact/signals/utils` предоставляет дополнительные вспомогательные компоненты и хуки, упрощающие работу с сигналами.
@@ -969,4 +969,4 @@ function Component() {
969
969
- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.
970
970
- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.
971
971
972
-
> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.
972
+
> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.
0 commit comments