1.1.14 • Published 3 years ago

@wowissu/vux v1.1.14

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

@wowissu/vux

vue typescript

Like Vuex, but base on Vue3 composition API.

import { reactive } from 'vue';

export function createStore(
  stateCaller: () => reactive({ [key: string]: any }),
  getterCaller: ({state}) => { [key: string]: any },
  mutateCaller: ({state, getter}) => { [key: string]: () => void },
  actionCaller: ({state, getter, mutate}) => { [key: string]: () => any }
)
  • StateCaller() must return reactive({ ... })
  • GetterCaller() recommand return the computed(() => 'your getter').
  • MutateCaller() state is only writable in mutate methods.
  • ActionCaller() the state or mutate both readonly in action methods, call mutate method for change the state.

How to use

// foo.store.ts
import { reactive, computed } from 'vue';
import { createStore } from '@wowissu/vux';

export const store = createStore(
  // state caller
  () => reactive({
    foo: false
  }),

  // getter caller
  ({ state }) => ({
    reverseFoo: computed(() => !state.foo)
  }),

  // mutate caller
  ({ state, getter }) => ({
    setFoo(bar: boolean) {
      state.foo = bar;
    }
  }),

  // action caller
  ({ state, mutate, getter }) => ({
    doAction() {
      mutate.setFoo(!state.foo)
    }
  })
)

Dynamic make store

Initialize the store only the first time when useStore() is called, and return the same one at other times

// foo.store.ts
import { reactive, computed } from 'vue';
import { createStore } from '@wowissu/vux';

const makeStore = () => createStore(
  // ... as above ...
)

let store!: ReturnType<typeof makeStore>

export const useStore() {
  return store ??= makeStore()
}

In Vue

import { useStore } from 'foo.store.ts';

export default defineComponent({
  // ...
  setup () {
    const { state, getter } = useStore();

    // use computed to watch data
    const foo = computed(() => state.foo)

    // or return the getter which already wrap by computed
    const reverseFoo = getter.reverseFoo

    return { foo, reverseFoo }
  }
})

Separate

If like all separate. try below.

📦bar
 ┣ 📜action.ts
 ┣ 📜getter.ts
 ┣ 📜index.ts
 ┣ 📜mutate.ts
 ┗ 📜state.ts
// bar/index.ts

import { createStore } from '@wowissu/vux';
import { stateCaller } from './state';
import { getterCaller } from './getter';
import { mutateCaller } from './mutate';
import { actionCaller } from './action';

const genStore = () => createStore(
  stateCaller,
  getterCaller,
  mutateCaller,
  actionCaller
);


// store into memory
let store!: ReturnType<typeof genStore>

// export
export const useBarStore = () => {
  return store ??= genStore();
}
// bar/state.ts
import { reactive } from 'vue'

export type State = ReturnType<typeof stateCaller>;

export const stateCaller = () => reactive({
  foo: false
});
// bar/getter.ts
import { computed } from 'vue';
import { GetterContext } from '@wowissu/vux';
import { State } from './state';

export type Getter = ReturnType<typeof getterCaller>;

export const getterCaller = ({ state }: GetterContext<State>) => ({
  reverseFoo: computed(() => !state.foo)
});
// bar/mutate.ts
import { MutateContext } from '@wowissu/vux';
import { Getter } from './getter';
import { State } from './state';

export type Mutate = ReturnType<typeof mutateCaller>;

export const mutateCaller = ({ state }: MutateContext<State, Getter>) => ({
  setFoo(val: boolean) {
    state.foo = val;
  }
});
// bar/action.ts
import { ActionContext } from '@wowissu/vux';
import { Getter } from './getter';
import { Mutate } from './mutate';
import { State } from './state';

export const actionCaller = ({ state, mutate }: ActionContext<State, Getter, Mutate>) => ({
  toggleFoo () {
    mutate.setFoo(!state.foo)
  }
});

:warning: Async Store

:warning: Async stateCaller is unrecommended. should consider to use async Action method for fetch data and change the state via mutate at first.

Fetch the data before init state.

createStore(
  // async state caller
  async () => {
    const data = await fetchSomeData();

    return reactive({
      data
    })
  }
)

Use in async vue

If you want use Async Component, please wrap with \<suspebnse \/> component.

import { computed } from 'vue';
import { useStore } from 'store.ts';

export default defineComponent({
  // ...
  async setup () {
    const { state, action } = await useStore();
    const foo = computed(() => state.foo)

    return { foo }
  }
})
1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.1.6

3 years ago

1.1.5

3 years ago

1.1.12

3 years ago

1.1.11

3 years ago

1.1.10

3 years ago

1.1.14

3 years ago

1.1.13

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago