Slim.js — это лёгкая библиотека для создания реактивных компонентов в JavaScript, предоставляющая минималистичный, но мощный API для управления состоянием и обновления DOM. В сочетании с Redux она позволяет централизованно управлять глобальным состоянием приложения, сохраняя преимущества реактивного рендеринга.
Redux реализует концепцию единого хранилища (store) и
предсказуемых изменений состояния через actions и
reducers. В Slim.js интеграция с Redux строится вокруг
подписки компонентов на изменения состояния и диспатча действий.
Для начала требуется импортировать необходимые элементы Redux:
import { createStore } from 'redux';
import Slim from 'slim-js';
Создаём базовый редуктор и хранилище:
const initialState = {
counter: 0
};
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, counter: state.counter + 1 };
case 'DECREMENT':
return { ...state, counter: state.counter - 1 };
default:
return state;
}
}
const store = createStore(counterReducer);
Slim.js-компонент может подписываться на изменения состояния следующим образом:
class CounterComponent extends Slim {
get useShadow() {
return false;
}
onBeforeCreated() {
this.state = store.getState();
store.subscribe(() => {
this.state = store.getState();
this.render();
});
}
increment() {
store.dispatch({ type: 'INCREMENT' });
}
decrement() {
store.dispatch({ type: 'DECREMENT' });
}
render() {
return `
<div>
<h2>Счётчик: ${this.state.counter}</h2>
<button oncl ick="this.increment()">+</button>
<button oncl ick="this.decrement()">-</button>
</div>
`;
}
}
Slim.define('counter-component', CounterComponent);
Ключевые моменты:
onBeforeCreated используется для инициализации
локального состояния из Redux и подписки на изменения.store.subscribe() гарантирует, что компонент
будет реагировать на любые изменения в хранилище.Slim.js поддерживает реактивные свойства через геттеры/сеттеры. Для интеграции с Redux можно создать вспомогательный метод, который автоматически обновляет компонент при изменении состояния.
class ReactiveComponent extends Slim {
get useShadow() {
return false;
}
onBeforeCreated() {
this.reduxState = store.getState();
store.subscribe(() => this.updateState(store.getState()));
}
updateState(newState) {
this.reduxState = newState;
this.render();
}
}
Этот подход позволяет компоненту не обращаться к глобальному
store в каждом методе, а работать с реактивной локальной
копией состояния.
Для сложных приложений с несколькими модулями состояния полезно разделять редукторы:
import { combineReducers, createStore } from 'redux';
const userReducer = (state = { name: '' }, action) => {
switch (action.type) {
case 'SET_NAME':
return { ...state, name: action.payload };
default:
return state;
}
};
const settingsReducer = (state = { theme: 'light' }, action) => {
switch (action.type) {
case 'SET_THEME':
return { ...state, theme: action.payload };
default:
return state;
}
};
const rootReducer = combineReducers({
user: userReducer,
settings: settingsReducer
});
const store = createStore(rootReducer);
Компоненты Slim.js могут подписываться на отдельные ветки состояния, минимизируя лишние перерисовки:
class UserComponent extends Slim {
get useShadow() { return false; }
onBeforeCreated() {
this.user = store.getState().user;
store.subscribe(() => {
const newUser = store.getState().user;
if (newUser !== this.user) {
this.user = newUser;
this.render();
}
});
}
setName(name) {
store.dispatch({ type: 'SET_NAME', payload: name });
}
render() {
return `
<div>
<p>Имя: ${this.user.name}</p>
<input type="text" onin put="this.setName(this.value)" placeholder="Введите имя"/>
</div>
`;
}
}
Slim.define('user-component', UserComponent);
Особенности:
Redux поддерживает middleware, например redux-thunk, для
обработки асинхронных действий:
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
const fetchUser = () => async (dispatch) => {
const response = await fetch('/api/user');
const data = await response.json();
dispatch({ type: 'SET_USER', payload: data });
};
const store = createStore(rootReducer, applyMiddleware(thunk));
Slim.js-компоненты могут вызывать такие асинхронные действия:
class AsyncUserComponent extends Slim {
get useShadow() { return false; }
onBeforeCreated() {
this.user = store.getState().user;
store.subscribe(() => {
this.user = store.getState().user;
this.render();
});
}
loadUser() {
store.dispatch(fetchUser());
}
render() {
return `
<div>
<p>Имя: ${this.user.name || 'Загрузка...'}</p>
<button oncl ick="this.loadUser()">Загрузить данные</button>
</div>
`;
}
}
Slim.define('async-user-component', AsyncUserComponent);
Асинхронные действия позволяют отделять логику получения данных от компонентов и поддерживают чистоту архитектуры.
redux-thunk или redux-saga).С помощью этих подходов Slim.js становится эффективным инструментом для построения реактивного интерфейса с централизованным управлением состоянием через Redux, сочетая простоту компонентов с предсказуемостью и масштабируемостью архитектуры.