Mithril — минималистичный фреймворк для создания одностраничных приложений на JavaScript. Одной из ключевых задач при разработке крупных приложений является управление состоянием, особенно если оно используется в разных компонентах. В Mithril подход к глобальному состоянию отличается простотой и гибкостью, что позволяет избежать громоздких решений вроде Redux, если приложение не требует сложной логики.
Для организации глобального состояния часто используют единый объект или набор объектов, доступных во всех компонентах:
const store = {
user: null,
todos: [],
isLoading: false
};
Здесь store хранит все данные, которые должны быть
доступны глобально. Его структура может быть произвольной, но
рекомендуется четко разделять данные по категориям для удобства
поддержки.
Изменение состояния осуществляется напрямую через объекты
store. Например:
function addTodo(text) {
store.todos.push({ text, completed: false });
m.redraw(); // перерисовка компонентов после изменения состояния
}
function setUser(user) {
store.user = user;
m.redraw();
}
Ключевой момент: Mithril не отслеживает автоматически
изменения в объектах, поэтому после любых модификаций
необходимо явно вызывать m.redraw(), чтобы обновить
интерфейс.
Для упрощения управления состоянием можно использовать паттерн подписки на изменения. Например, создать функцию-обертку для наблюдаемого состояния:
function observable(initialValue) {
let value = initialValue;
const subscribers = [];
return {
get: () => value,
set: (newValue) => {
value = newValue;
subscribers.forEach(fn => fn(value));
m.redraw();
},
subscribe: (fn) => subscribers.push(fn)
};
}
const count = observable(0);
count.subscribe((val) => console.log("New value:", val));
count.set(1); // в консоли: New value: 1
Такой подход позволяет компонентам подписываться на изменения конкретных частей состояния и обновляться только при необходимости.
Компоненты Mithril получают доступ к глобальному состоянию напрямую или через функции-обертки. Пример использования глобального хранилища в компоненте:
const TodoList = {
view: () => m("ul", store.todos.map(todo =>
m("li", { class: todo.completed ? "done" : "" }, todo.text)
))
};
const App = {
view: () => m("div", [
m("h1", "Todo App"),
m(TodoList)
])
};
m.mount(document.body, App);
Любое изменение store.todos и вызов
m.redraw() приведет к автоматической перерисовке списка
задач.
Для асинхронных запросов глобальное состояние может содержать флаги загрузки и ошибки:
function fetchTodos() {
store.isLoading = true;
m.redraw();
fetch("/api/todos")
.then(res => res.json())
.then(data => {
store.todos = data;
store.isLoading = false;
m.redraw();
})
.catch(() => {
store.isLoading = false;
m.redraw();
});
}
Компоненты могут отображать индикатор загрузки на основе
store.isLoading:
const Loader = {
view: () => store.isLoading ? m("p", "Загрузка...") : null
};
Для крупных приложений рекомендуется разделять глобальное состояние на модули:
const userStore = {
user: null,
setUser(user) {
this.user = user;
m.redraw();
}
};
const todoStore = {
todos: [],
addTodo(todo) {
this.todos.push(todo);
m.redraw();
}
};
Это облегчает поддержку, тестирование и масштабирование приложения, сохраняя при этом принцип единого источника правды.
Глобальное состояние в Mithril строится вокруг простых объектов и функций. Основные правила:
m.redraw().Такой подход обеспечивает простую, но эффективную систему глобального управления состоянием, которая масштабируется с ростом приложения и легко интегрируется с компонентной архитектурой Mithril.