/vuex-class-component

use ECMAScript / TypeScript class-style write vuex module. use class-style call store's methods

Primary LanguageTypeScriptMIT LicenseMIT

vuex-class-component

use ECMAScript / TypeScript write Vuex

UPDATE !!!

Vue 2.6.0 provided a function - Vue.observable. Then the state classes of store can use it to make itself observable. This way is enough to me.

./store/UserState.ts

export default class UserState {
  public id: string = "id";
  public sex: number = 1;
  public names: string[] = [];
  public config: { [name: string]: any } = {};

  public addConfig(key: stirng, value: any) {
    //use Vue.set to make change observable
    Vue.set(config, key, value);
  }
}

./store/index.ts

let userState = Vue.observable(new UserState());
let store = { userState };
Vue.prototype.$store = store;
export default store;

./App.vue

<template>
  <!-- name will change -->
  <div id="app">{{$store.userState.name}}</div>
</template>

Example -------------------------------

define moudles @/store/modules/user.ts

import {
  VuexClass,
  Constructor,
  Getter,
  Mutation,
  Action,
  Exclude
} from "vuex-class-component";

// state
@VuexClass({ name: "user" })
export default class UserState {
  //convert to => store.state.user.id
  //convert to => store.mutations["user/id"]
  public id: string = "id";

  //convert to => store.state.user.sex
  //convert to => store.getters["user/sex"]
  //convert to => store.mutations["user/sex"]
  @Getter
  public sex: number = 1;

  // won't add to store
  @Exclude
  public name: string = "";

  // since in VuexClass function
  // we will new UserState() to get some instance variables
  // so it's not recommand add initialize function here
  // instead use @Constructor
  // it'll be called when we new UserState()
  constructor() {}

  @Constructor
  public init() {}

  //convert to => store.getters["user/getNameWithSex"]
  @Getter
  public getNameWithSex(sex: number): string {
    if (sex == 1) {
      return sex + "_" + this._name;
    }
    return this._name;
  }

  //convert to => store.mutations["user/setNameWithSex"]
  @Mutation
  public setNameWithSex(sex: number) {
    if (sex == 1) {
      this._name = sex + "_" + this._name;
    }
  }

  //convert to => store.actions["user/change"]
  //Action will always return a Promise Instance
  @Action
  public change(newName: string, newSex: number): Promise<any> {
    return http
      .request({
        url: "/user_change",
        method: "post",
        data: {
          newName,
          newSex
        }
      })
      .then(
        (response: any): any => {
          return response;
        }
      );
  }

  // won't add to store
  private fillData() {
    //...
  }

  // won't add to store
  @Exclude
  private doTest() {
    console.log("just a test");
  }
}

define store @/store/index.ts

import Vue from "vue";
import Vuex from "vuex";
import User from "./modules/user";
import { createStore } from "./vuex-class-component";

Vue.use(Vuex);

//modules
export let user: User = new User();

//store
const store = createStore(false, {
  user
});
export default store;

use in .vue @/app.vue

<template>
  <div id="app"></div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import store, { user } from "@/store";

@Component
export default class App extends Vue {
  created() {
    //state
    console.log(store.state.user.id, user.id);

    //getter
    console.log(store.getters["user/name"], user.name);
    console.log(
      store.getters["user/getNameWithSex"]("1"),
      user.getNameWithSex("1")
    );

    //mutation
    store.commit("user/nickName", "nickName");
    user.nickName = "nickName";
    store.commit("user/setNameWithSex", "1");
    user.setNameWithSex("1");

    //action
    store.dispatch("user.change", ["newName", "newSex"]); //store方式调用action ,不支持多参数
    user.change("newName", "newSex");
  }
}
</script>

@VuexClass

//1.namespaced=false
@VuexClass
export default class App {}

//2.namaspaced=true
@VuexClass({ name: "app" })
export default class App {}

use "root"

let root = new Root();
let user = new User();
const store = createStore(false, {
  root: root,
  user,
  ...
});

get vuex args inside function

import {GetterArgs,MutationArgs,ActionArgs} from "vuex-class-component"
//Getter
public get name():string{
    let args:GetterArgs=arguments[arguments.length-1]
    ...
}
//Mutation
public set name():string{
    let args:MutationArgs=arguments[arguments.length-1]
    ...
}
//Action
public change(newName:string,newSex:number):any{
    let args:ActionArgs=arguments[arguments.length-1]
    ...
}

support arg default value

import {Getter,Mutation,GetterArgs,MutationArgs,ActionArgs} from "vuex-class-component"

@Getter
public getByID(id:number=1):any{
    let args:GetterArgs=arguments[arguments.length-1]
    ...
}

@Mutation
public getByName(name:string="aaa"):any{
    let args:MutationArgs=arguments[arguments.length-1]
    ...
}

//
public change(newName:string,newSex:number="default"):any{
    let args:ActionArgs=arguments[arguments.length-1]
    ...
}