Flux — это архитектурный паттерн, разработанный Facebook для управления состоянием приложений с пользовательским интерфейсом. Основная цель Flux — упрощение управления сложными состояниями за счёт однонаправленного потока данных. В отличие от традиционных MVC-подходов, Flux предотвращает двусторонние зависимости между компонентами, что делает приложение более предсказуемым и легко отлаживаемым.
Flux состоит из нескольких ключевых сущностей, каждая из которых выполняет строго определённую функцию:
Actions — это объекты, содержащие описание события, которое произошло в приложении. Обычно они включают:
type — строковой идентификатор действияpayload — дополнительные данные, необходимые для
обработки действияПример Action в Jav * aScript:
const addTodoAction = {
type: 'ADD_TODO',
payload: { id: 1, text: 'Купить хлеб' }
};
Actions являются единственным источником информации о событиях, которые могут изменить состояние приложения.
Dispatcher — это центральный механизм, который распределяет Actions по всем зарегистрированным Stores. Он обеспечивает, что все Stores получают одно и то же событие в согласованном порядке.
Пример использования Dispatcher:
import { Dispatcher } from 'flux';
const dispatcher = new Dispatcher();
dispatcher.register((action) => {
switch(action.type) {
case 'ADD_TODO':
console.log('Добавление задачи:', action.payload);
break;
}
});
Dispatcher не содержит логики изменения состояния — его задача исключительно в маршрутизации Actions.
Stores хранят состояние приложения и бизнес-логику. Каждый Store подписан на Dispatcher и обновляет своё состояние при получении соответствующих Actions. После изменения состояния Store уведомляет подписчиков (например, компоненты UI) через события.
Пример Store для управления списком задач:
import { EventEmitter } from 'events';
import dispatcher from './dispatcher';
class TodoStore extends EventEmitter {
constructor() {
super();
this.todos = [];
}
getTodos() {
return this.todos;
}
handleAction(action) {
switch(action.type) {
case 'ADD_TODO':
this.todos.push(action.payload);
this.emit('change');
break;
}
}
}
const todoStore = new TodoStore();
dispatcher.register(todoStore.handleAction.bind(todoStore));
export default todoStore;
Ключевой момент: Stores содержат логику изменения состояния, но не знают о UI. Это гарантирует независимость состояния от представления.
Views — это компоненты UI, которые подписываются на изменения Stores. При получении события изменения состояния View обновляет отображение данных. В контексте Inferno Views обычно реализуются как компоненты, которые используют состояние Store через подписку.
Пример подписки View на Store в Inferno:
import { Component } from 'inferno';
import todoStore from './TodoStore';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
todos: todoStore.getTodos()
};
}
componentDidMount() {
todoStore.on('change', () => {
this.setState({ todos: todoStore.getTodos() });
});
}
render() {
return (
<ul>
{this.state.todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
</ul>
);
}
}
Flux основан на строгом однонаправленном потоке данных:
Преимущества:
Inferno поддерживает работу с Flux аналогично React. Основные рекомендации:
Пример создания глобального TodoStore с Inferno:
import { createStore } from 'flux/utils';
import dispatcher from './dispatcher';
class TodoStore extends createStore {
constructor() {
super(dispatcher);
this.todos = [];
}
__onDispatch(action) {
if (action.type === 'ADD_TODO') {
this.todos.push(action.payload);
this.__emitChange();
}
}
getTodos() {
return this.todos;
}
}
export default new TodoStore();
'change',
'update'), чтобы обеспечить гибкость подписки
компонентов.Flux обеспечивает прозрачную, предсказуемую систему управления состоянием с однонаправленным потоком данных, что особенно важно в крупных приложениях на Inferno, где компоненты часто обновляют состояние независимо друг от друга. Правильная организация Actions, Dispatcher, Stores и Views позволяет строить масштабируемые интерфейсы без хаоса в состоянии.