rvm-toolkit
v2.1.0
Published
Tools to help build apps based on the MVVM pattern using React and mobx.
Readme
rvm-toolkit
Примеры и демо: https://g28xyz.github.io/rvm-toolkit/
Библиотека для MVVM‑подхода на базе MobX + React. Содержит:
- Model: управление состоянием, валидации, сериализация, откат/коммит.
- Decorators: field/validation/submit/exclude/PropFromView/MakeObservable.
- Command: asyncCommand для работы с async-операциями, ошибками и конкурентностью.
- View: обертка для проброса ViewModel и жизненный цикл onInit/onDispose.
- Vite‑плагин: генерация контейнеров типов для DI.
Зачем и чем помогает
rvm-toolkit нужен, когда бизнес‑логика и состояние React‑приложения начинают расползаться по компонентам. Он задает понятную структуру MVVM поверх MobX: Model отвечает за данные и валидацию, Store — за коллекции, ViewModel — за сценарии UI, а View остается чистой.
- Меньше бойлерплейта: декораторы связывают поля модели с сериализацией и MobX‑наблюдаемостью.
- Управляемые изменения:
model.serviceдаетdirty,dumpDataи операцииcommit/reject/toInit, что удобно для форм и черновиков. - Списки и загрузки без хаоса:
StoreBase+@Storeупрощают CRUD, фильтры и загрузку данных (см.docs/store.mdиexamples/todo-list). - DI и композиция ViewModel:
@Service,@Inject,@InjectStore,view()подключают зависимости и жизненный циклonInit/onDispose. - Типобезопасность: Vite‑плагин генерирует DI‑типы.
Документация
- https://g28xyz.github.io/rvm-toolkit/docs/
Быстрый старт
1) Model + decorators
import { Model, field, validation, submit, exclude } from "rvm-toolkit";
interface UserDto {
id: number;
name: string;
token: string;
}
class UserModel extends Model<UserDto> {
@field
id = 0;
@field
@validation((value) => (value ? "" : "name required"))
name = "";
@field
@exclude(true)
token = "";
@field
@submit((value) => value.trim())
trimmedName = "";
}
const model = new UserModel({ id: 1, name: "Alice", token: "secret" });
model.name = "";
console.log(model.service.validation.name); // "name required"
console.log(model.service.dumpData); // { id: 1, name: "", trimmedName: "" }