Skip to content

Introduction

Vue Modeler is a comprehensive solution for state management in Vue.js applications, consisting of two complementary libraries:

Key concepts

  • Model instead of store. No global state store. No store — no problem. State is encapsulated in the model and is reactive. Outside the model it is read-only and observable. Destroying the model destroys the state.

  • Action — object with reactive state and behavior. Inside the model class, Action is an async method that changes state; outside (in components and other models) — a reactive object with state and behavior.

  • Dependencies via injection and dependency container

    • The model receives dependencies as constructor arguments. No direct imports from other modules. This makes it easy to extract related models into separate modules and reuse in other projects.

    • No need to think about how to create, get, or remove a model after use — the container handles it.

Key features

  • OOP-based. Model is defined as a standard class. Inheritance, encapsulation, polymorphism, destructor are available by default.

  • Type safety preserved. All autocomplete hints work both inside and outside the class context.

  • Vue reactivity. Everything works on top of Vue reactivity. No need to learn extra APIs or approaches for reactive objects.

  • Easy testing. @vue-modeler/model lets you write less code, which means fewer tests. Testing models is the same as testing plain class instances.


Why it was created

Boilerplate in actions

Problem: Actions are often accompanied by repetitive code to track execution state via extra variables: isLoading, isPending. This code adds no business value but bloats the codebase.

Solution: Action is an object with reactive properties reflecting its execution status: ready, pending, lock, abort, error. No extra code needed.

Cancelling or locking an action

Problem: Cancelling or locking an action is uncommon but necessary. Everyone solves it differently, but the pattern is the same. Different implementations of the same pattern make maintenance and reuse harder.

Solution: Action provides lock and abort methods for locking and cancelling. No extra code to write or maintain.

Exception handling

Problem: Exception handling is an extra source of issues:

  • developers forget about it;
  • each developer handles it differently;
  • guidelines don't guarantee exceptions are handled correctly;
  • handling always needs careful code review.

Solution: Action catches exceptions, stores them as part of state and provides a single interface for handling. Developers can't handle them differently.

Outdated patterns

Problem: Pinia uses an outdated factory function pattern for stores. That approach brings extra patterns to emulate inheritance and polymorphism.

Solution: Class and OOP support out of the box.

Too much reactivity

Problem: A Pinia store is an object with reactive properties. But inside the factory function those are reactive variables created with Vue's Reactivity API. You get double reactivity and different interfaces for the same data.

Solution: Models are shallow reactive objects out of the box. Public and protected properties are reactive both outside and inside without explicitly using Vue's reactivity API.

Released under the MIT License.