All Projects → championswimmer → Vuex Module Decorators

championswimmer / Vuex Module Decorators

Licence: mit
TypeScript/ES7 Decorators to create Vuex modules declaratively

Programming Languages

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

Projects that are alternatives of or similar to Vuex Module Decorators

Multivisor
Centralized supervisor WebUI and CLI
Stars: ✭ 104 (-93.93%)
Mutual labels:  vuex
Vue Crypto Dashboard
Cryptocurrency Dashboard made with Vue
Stars: ✭ 107 (-93.76%)
Mutual labels:  vuex
Mpvue Vuex Demo
用mpvue构建的小程序-vue模板项目,还引入了vuex,sass,flyio等
Stars: ✭ 112 (-93.47%)
Mutual labels:  vuex
Vue Mobile Starter
☘ A starter project structure for Vue.js app.
Stars: ✭ 105 (-93.87%)
Mutual labels:  vuex
Vue Laravel Spa
Single Page Application made with Vue.JS2, Vue Router, Vuex and Laravel 5.6.
Stars: ✭ 107 (-93.76%)
Mutual labels:  vuex
Ruoyi Vue Fast
(RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统
Stars: ✭ 107 (-93.76%)
Mutual labels:  vuex
Vuejs 2 Na Pratica
Curso totalmente prático de Vue.js da Webschool
Stars: ✭ 101 (-94.11%)
Mutual labels:  vuex
Learn Vuex
🗂Source code for the Vuex for Everyone course
Stars: ✭ 113 (-93.41%)
Mutual labels:  vuex
Vue2 Elm
基于 vue2 + vuex 构建一个具有 45 个页面的大型单页面应用
Stars: ✭ 37,325 (+2077.65%)
Mutual labels:  vuex
Vue Generator
A CLI generator for Vue components, views and store modules
Stars: ✭ 111 (-93.52%)
Mutual labels:  vuex
Vue Cli Multipage Bootstrap
vue-cli-multipage-bootstrap demo with vue2+vue-router+vuex+bootstrap+markdown for learning vue2.0
Stars: ✭ 105 (-93.87%)
Mutual labels:  vuex
Vue Mmplayer
🎵 基于 Vue 的在线音乐播放器(PC) Online music player
Stars: ✭ 1,632 (-4.78%)
Mutual labels:  vuex
Vlackjack
Blackjack built with Vue.js and vuex
Stars: ✭ 109 (-93.64%)
Mutual labels:  vuex
Iview Vue Admin
iView vue Admin / An admin management system template
Stars: ✭ 105 (-93.87%)
Mutual labels:  vuex
Seemusic
Vue 云音乐播放器,网易云音乐API,可听网易云高品质付费歌曲。 Vue music player
Stars: ✭ 112 (-93.47%)
Mutual labels:  vuex
Vue2 Shop
A shop developed with Vue2 + Vue-router + Axios + Vuex + Node + Express + MongoDB + Webpack
Stars: ✭ 103 (-93.99%)
Mutual labels:  vuex
Vue Meizi
vue最新实战项目,vue2 + vuex + webpack + es6 干货多多,新手福利
Stars: ✭ 1,476 (-13.89%)
Mutual labels:  vuex
Vue Ruby China
使用Vue.js框架搭建的ruby china山寨版,集成vue-router+vuex等
Stars: ✭ 113 (-93.41%)
Mutual labels:  vuex
Vue Mobile Cli
🚀 Vue移动端多页应用脚手架
Stars: ✭ 112 (-93.47%)
Mutual labels:  vuex
Electron Vue Cloud Music
🚀Electron + Vue 仿网易云音乐windows客户端
Stars: ✭ 1,894 (+10.5%)
Mutual labels:  vuex

vuex-module-decorators

Usage Guide Detailed Guide: https://championswimmer.in/vuex-module-decorators/

Typescript/ES7 Decorators to make Vuex modules a breeze

Build Status npm:size:gzip cdn:min:gzip codecov npm npm npm type definitions Maintainability Codacy Badge codebeat badge Total alerts Language grade: JavaScript

Patrons

While I have a day job and I really maintain open source libraries for fun, any sponsors are extremely graciously thanked for their contributions, and goes a long way 😇 ❤️

CHANGELOG

  • There are major type-checking changes (could be breaking) in v0.9.7

  • There are major usage improvements (non backwards compatible) in 0.8.0

Please check CHANGELOG

Examples

Read the rest of the README to figure out how to use, or if you readily want to jump into a production codebase and see how this is used, you can check out -

Installation

npm install -D vuex-module-decorators

Babel 6/7

NOTE This is not necessary for vue-cli@3 projects, since @vue/babel-preset-app already includes this plugin

  1. You need to install babel-plugin-transform-decorators

TypeScript

  1. set experimentalDecorators to true
  2. For reduced code with decorators, set importHelpers: true in tsconfig.json
  3. (only for TypeScript 2) set emitHelpers: true in tsconfig.json

Configuration

Using with target: es5

NOTE Since version 0.9.3 we distribute as ES5, so this section is applicable only to v0.9.2 and below

This package generates code in es2015 format. If your Vue project targets ES6 or ES2015 then you need not do anything. But in case your project uses es5 target (to support old browsers), then you need to tell Vue CLI / Babel to transpile this package.

// in your vue.config.js
module.exports = {
  /* ... other settings */
  transpileDependencies: ['vuex-module-decorators']
}

Usage

The conventional old & boring way

Remember how vuex modules used to be made ?

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

Hello Decorators !

Well not anymore. Now you get better syntax. Inspired by vue-class-component

import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'

@Module
export default class Counter2 extends VuexModule {
  count = 0

  @Mutation
  increment(delta: number) {
    this.count += delta
  }
  @Mutation
  decrement(delta: number) {
    this.count -= delta
  }

  // action 'incr' commits mutation 'increment' when done with return value as payload
  @Action({ commit: 'increment' })
  incr() {
    return 5
  }
  // action 'decr' commits mutation 'decrement' when done with return value as payload
  @Action({ commit: 'decrement' })
  decr() {
    return 5
  }
}

async MutationAction === magic

Want to see something even better ?

import { Module, VuexModule, MutationAction } from 'vuex-module-decorators'
import { ConferencesEntity, EventsEntity } from '@/models/definitions'

@Module
export default class HGAPIModule extends VuexModule {
  conferences: Array<ConferencesEntity> = []
  events: Array<EventsEntity> = []

  // 'events' and 'conferences' are replaced by returned object
  // whose shape must be `{events: [...], conferences: [...] }`
  @MutationAction({ mutate: ['events', 'conferences'] })
  async fetchAll() {
    const response: Response = await getJSON('https://hasgeek.github.io/events/api/events.json')
    return response
  }
}

Automatic getter detection

@Module
class MyModule extends VuexModule {
  wheels = 2

  @Mutation
  incrWheels(extra) {
    this.wheels += extra
  }

  get axles() {
    return this.wheels / 2
  }
}

this is turned into the equivalent

const module = {
  state: { wheels: 2 },
  mutations: {
    incrWheels(state, extra) {
      state.wheels += extra
    }
  },
  getters: {
    axles: (state) => state.wheels / 2
  }
}

Putting into the store

Use the modules just like you would earlier

import Vue from 'nativescript-vue'
import Vuex, { Module } from 'vuex'

import counter from './modules/Counter2'
import hgapi from './modules/HGAPIModule'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {},
  modules: {
    counter,
    hgapi
  }
})

Module re-use, use with NuxtJS

If you need to support module reuse or to use modules with NuxtJS, you can have a state factory function generated instead of a static state object instance by using stateFactory option to @Module, like so:

@Module({ stateFactory: true })
class MyModule extends VuexModule {
  wheels = 2

  @Mutation
  incrWheels(extra) {
    this.wheels += extra
  }

  get axles() {
    return this.wheels / 2
  }
}

this is turned into the equivalent

const module = {
  state() {
    return { wheels: 2 }
  },

  mutations: {
    incrWheels(state, extra) {
      state.wheels += extra
    }
  },
  getters: {
    axles: (state) => state.wheels / 2
  }
}

Dynamic Modules

Vuex allows us to register modules into store at runtime after store is constructed. We can do the following to create dynamic modules

interface StoreType {
  mm: MyModule
}
// Declare empty store first
const store = new Vuex.Store<StoreType>({})

// Create module later in your code (it will register itself automatically)
// In the decorator we pass the store object into which module is injected
// NOTE: When you set dynamic true, make sure you give module a name
@Module({ dynamic: true, store: store, name: 'mm' })
class MyModule extends VuexModule {
  count = 0

  @Mutation
  incrCount(delta) {
    this.count += delta
  }
}

If you would like to preserve the state e.g when loading in the state from vuex-persist

...

-- @Module({ dynamic: true, store: store, name: 'mm' })
++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: true })
class MyModule extends VuexModule {

...

Or when it doesn't have a initial state and you load the state from the localStorage

...

-- @Module({ dynamic: true, store: store, name: 'mm' })
++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: localStorage.getItem('vuex') !== null })
class MyModule extends VuexModule {

...

Accessing modules with NuxtJS

There are many possible ways to construct your modules. Here is one way for drop-in use with NuxtJS (you simply need to add your modules to ~/utils/store-accessor.ts and then just import the modules from ~/store):

~/store/index.ts:

import { Store } from 'vuex'
import { initialiseStores } from '~/utils/store-accessor'
const initializer = (store: Store<any>) => initialiseStores(store)
export const plugins = [initializer]
export * from '~/utils/store-accessor'

~/utils/store-accessor.ts:

import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import example from '~/store/example'

let exampleStore: example

function initialiseStores(store: Store<any>): void {
  exampleStore = getModule(example, store)
}

export { initialiseStores, exampleStore }

Now you can access stores in a type-safe way by doing the following from a component or page - no extra initialization required.

import { exampleStore } from '~/store'
...
someMethod() {
  return exampleStore.exampleGetter
}

Using the decorators with ServerSideRender

When SSR is involved the store is recreated on each request. Every time the module is accessed using getModule function the current store instance must be provided and the module must be manually registered to the root store modules

Example

// store/modules/MyStoreModule.ts
import { Module, VuexModule, Mutation } from 'vuex-module-decorators'

@Module({
  name: 'modules/MyStoreModule',
  namespaced: true,
  stateFactory: true,
})
export default class MyStoreModule extends VuexModule {
  public test: string = 'initial'

  @Mutation
  public setTest(val: string) {
    this.test = val
  }
}


// store/index.ts
import Vuex from 'vuex'
import MyStoreModule from '~/store/modules/MyStoreModule'

export function createStore() {
  return new Vuex.Store({
    modules: {
      MyStoreModule,
    }
  })
}

// components/Random.tsx
import { Component, Vue } from 'vue-property-decorator';
import { getModule } from 'vuex-module-decorators';
import MyStoreModule from '~/store/modules/MyStoreModule'

@Component
export default class extends Vue {
    public created() {
        const MyModuleInstance = getModule(MyStoreModule, this.$store);
        // Do stuff with module
        MyModuleInstance.setTest('random')
    }
}

Configuration

There is a global configuration object that can be used to set options across the whole module:

import { config } from 'vuex-module-decorators'
// Set rawError to true by default on all @Action decorators
config.rawError = true
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].