All Projects → guyskk → hami-vuex

guyskk / hami-vuex

Licence: MIT license
🍈 Hami melon flavored Vuex, modular by design, completely TypeScript intelligence, state management for Vue.js.

Programming Languages

javascript
184084 projects - #8 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to hami-vuex

yurt
high quality mounted real (e)states
Stars: ✭ 53 (+178.95%)
Mutual labels:  state-management
asyncmachine
Relational State Machine with a visual inspector
Stars: ✭ 67 (+252.63%)
Mutual labels:  state-management
immutable-cursor
👊 Immutable cursors incorporating the Immutable.js interface over a Clojure-inspired atom
Stars: ✭ 58 (+205.26%)
Mutual labels:  state-management
storken
🦩 Storken is a React State Manager. Simple as `useState`.
Stars: ✭ 22 (+15.79%)
Mutual labels:  state-management
ngx-mobx
Mobx decorators for Angular Applications
Stars: ✭ 14 (-26.32%)
Mutual labels:  state-management
nstate
A simple but powerful react state management library with low mind burden
Stars: ✭ 11 (-42.11%)
Mutual labels:  state-management
crypto-currency
A Flutter application showing crypto currency rates.
Stars: ✭ 16 (-15.79%)
Mutual labels:  state-management
unstated
Simple state management for react
Stars: ✭ 12 (-36.84%)
Mutual labels:  state-management
almy
🗄️ 673 bytes store for managing the state in your application
Stars: ✭ 26 (+36.84%)
Mutual labels:  state-management
UniTEA
Implementation of The Elm Architecture for Unity3D
Stars: ✭ 31 (+63.16%)
Mutual labels:  state-management
gstate
A crazy state management for lazy programmers
Stars: ✭ 27 (+42.11%)
Mutual labels:  state-management
mst-effect
💫 Designed to be used with MobX-State-Tree to create asynchronous actions using RxJS.
Stars: ✭ 19 (+0%)
Mutual labels:  state-management
XUI
XUI makes modular, testable architectures for SwiftUI apps a breeze!
Stars: ✭ 100 (+426.32%)
Mutual labels:  state-management
quick-redux
helper functions to make redux and react development quicker
Stars: ✭ 61 (+221.05%)
Mutual labels:  state-management
flutter super state
A simple super state management library for Flutter (with async support)
Stars: ✭ 22 (+15.79%)
Mutual labels:  state-management
reactive-states
Reactive state implementations (brainstorming)
Stars: ✭ 51 (+168.42%)
Mutual labels:  state-management
NObservable
MobX like observable state management library with Blazor support
Stars: ✭ 66 (+247.37%)
Mutual labels:  state-management
snap-state
State management in a snap 👌
Stars: ✭ 23 (+21.05%)
Mutual labels:  state-management
query-param-store
Angular Reactive Query Parameters Store
Stars: ✭ 15 (-21.05%)
Mutual labels:  state-management
hoox
Functional react state management base on hooks
Stars: ✭ 80 (+321.05%)
Mutual labels:  state-management

Hami-Vuex 🍈 (hami melon flavored)

npm package build status code coverage

查看中文文档

Hami melon flavored Vuex! State management for Vue.js

Features:

  • Build on Vuex, compatible with Vuex 3 & 4
  • Also compatible with Vue 2 and Vue 3
  • Modular by design, no more fat store
  • Completely TypeScript intelligence support
  • Unit tests line coverage: 100%

Usage

npm install --save hami-vuex

Create Hami Vuex instance

// store/index.js
import { createHamiVuex } from 'hami-vuex'
export const hamiVuex = createHamiVuex({
    vuexStore: /* the Vuex Store instance, created according to Vuex docs */
})

Or use the default empty Vuex Store instance, Vue 2 + Vuex 3 Writing:

import Vue from 'vue'
import Vuex from 'vuex'
import { createHamiVuex } from 'hami-vuex'

Vue.use(Vuex)

export const hamiVuex = createHamiVuex({
    /* Optional:Vuex Store constructor options */
})

And Vue 3 + Vuex 4 Writing:

import { createApp } from 'vue'
import { createHamiVuex } from 'hami-vuex'

export const hamiVuex = createHamiVuex({
    /* Optional:Vuex Store constructor options */
})

export const app = createApp()
app.use(hamiVuex)

The Hami Vuex instance is for create and manage Hami Store instances, all business logics should implemented by Hami Store instances.

Create a Counter Store

// store/counter.js
import { hamiVuex } from '@/store/index'

// Internal:dynamic registered Vuex module
export const counterStore = hamiVuex.store({

    // unique name of the store, will appear in devtools
    $name: 'counter',

    // define the state with plain object(will auto deep copy it)
    $state: {
        count: 0,
    },

    // or a function that returns a fresh state
    $state() {
        return { count: 0 }
    }

    // define a getter, similar to Vue computed
    get double() {
        return this.count * 2
    },

    // define an action, similar to Vuex action
    increment() {
        // $patch is builtin Vuex mutation, used for update state
        // it accepts K:V object, will shallow asign to state
        this.$patch({
            count: this.count + 1
        })
        // for complex operation, can use a mutator function
        this.$patch(state => {
            state.count = this.count + 1
        })
    },

    // also define an async action, similar to Vuex action
    async query() {
        let response = await http.get('/counter')
        this.$patch({
            count: response.count
        })
    }
})

We don't need define mutations, the builtin $patch mutation can handle all tasks.

Use Counter Store in Vue component

import { counterStore } from '@/store/counter'

export default {
    computed: {
        // map state properties
        count: () => counterStore.count,
        // map getters
        double: () => counterStore.double
    },
    methods: {
        // map actions
        increment: counterStore.increment,
    },
    async mounted() {
        // call actions, or use properties
        await counterStore.query()
        console.log(counterStore.count)
    },
    destroyed() {
        // the $reset method will reset to initial state
        counterStore.$reset()
    }
}

Congratulations, you can enjoy the hami melon flavored Vuex!

TypeScript Support

Hami-Vuex completely support TypeScript, you can configure TypeScript to make type inference smarter (better code intelligence).

// tsconfig.json
{
  "compilerOptions": {
    // this aligns with Vue's browser support
    "target": "es5",
    // this enables stricter inference for data properties on `this`
    "strict": true,
  }
}

Detailed instructions: TypeScript Support - Vue.js

Advanced usage

If you don't need Vue SSR, you can skip the following advanced usages (which are not required in most cases).

In the above basic usage, the Store object is a stateful singleton, and using such an object in Vue SSR requires setting the runInNewContext parameter to true, which incurs a relatively large server performance overhead.

Advanced usage avoids "stateful singletons" and is suitable for use in the Vue 3 setup method, as well as for Vue optional writing.

Define a Counter Store

import { defineHamiStore } from 'hami-vuex'

// Note: Here is the capitalization of the initials CounterStore !
export const CounterStore = defineHamiStore({
    /* Here the parameters are the same as hamiVuex.store() */
})

Usage 1: Bind a Vuex Store instance

const vuexStore = /* Vuex Store instance */
const counterStore = CounterStore.use(vuexStore)
await counterStore.query()
console.log(counterStore.count)

Usage 2: Used in the Vue setup method

export default {
    setup() {
        const counterStore = CounterStore.use()
        await counterStore.query()
        console.log(counterStore.count)
    },
}

Usage 3: Used in Vue computed

export default {
    computed: {
        // Similar to Vuex mapActions, mapGetters
        counterStore: CounterStore.use,
        count: CounterStore.count,
        query: CounterStore.query,
    },
}

Usage 4: Use each other in the Store

const otherStore = defineHamiStore({
    get counterStore(){
        return CounterStore.use(this)
    },
    get count(){
        return this.counterStore.count
    }
})

References and acknowledgements

Special thanks to the above projects and materials for bringing me a lot of inspiration, and hope that Hami Vuex can bring new inspiration to the community!

Design considerations

Why use "stateful singleton"?

Stateful singletons are simpler and more convenient to use, and only perform poorly in terms of Vue SSR. Vue SSR is not required for most single-page applications, so you can use "stateful singleton" with confidence and switch to advanced usage if necessary.

Why write getters and actions at the same level?

Since TypeScript is difficult to type infer from the Vue optional interface, writing at the same level avoids this problem.

For specific reasons, please refer to the following information:

Why are $name and $state prefixed with $?

Because all fields need to avoid name conflicts after writing them at the same level, special fields are prefixed with $.

Why not use mutations anymore?

The advantage of using mutations is that it is more convenient to debug in devtools, the disadvantage is that the code is slightly more cumbersome. Another problem is that after writing all fields at the same level, it is difficult to distinguish between actions and mutations. After weighing it, it was decided not to use mutations.

Why not use Pinia?

After using Pinia for a while, I felt that the devtools plugin support was not very good and unstable. In addition, Pinia is not written in a way that is friendly enough for Vue optional usage, and should be caused by supporting Vue SSR.

Why is it based on Vuex?

I think Vuex itself does a good job, and improving the interface design can achieve the effect I want, without having to make the wheels repeatedly. And based on the Vuex implementation, it can be compatible with old code to the greatest extent, and it is easy to do smooth migration.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].