2018年12月7日 星期五

[Vue] Vuex – basis


 Vue.js   Vuex 


Introduction


Vuex is the official state management package for Vue.js.
We will learn the concept and basis usage of how to keep state by it.





Environment


Vue.js 2.5.11
Vue CLI 3.2.1
Vuex 3.0.01


Implement


Intall

$ npm install vuex --save


Import and Regiter

import Vuex from 'vuex'

Vue.use(Vuex);


Concept



Must Synchronous, to prevent the state from un-trackable
(Reference: Mutations Must Be Synchronous)
Used for commit mutations, can be asynchronous



Get started

Lets start by a simple example for tracking the “Count”.
We will ignore Actions here and just implement Mutations which includes:

1.  Increment
2.  Decrement
3.  Reset

vuex store (myStore.js)

import Vue from 'vue';
import Vuex from 'vuex'
Vue.use(Vuex)

export const INCREMENT = 'increment';
export const DECREMENT = 'decrement';
export const RESET = 'reset';

export const store = new Vuex.Store({
    state: {
      count: 0
    },
    mutations: {
      increment (state) {
        state.count++;
      },
      decrement(state){
          if(state.count > 0)
            state.count--;
      },
      reset(state){
          state.count= 0;
      }

    }
})


Usage

import {store, INCREMENT, DECREMENT, RESET} from "myStore";

//Increment
store.commit(INCREMENT);
//Decrement
store.commit(DECREMENT);
//Reset
store.commit(RESET);

We can use vue-devtools to monitor the state in Vuex store.




Inject Vuex store to components

Injecting the Vuex store to components can help us to stop importing the Store JS file (myStore.js) to every components.

import Vue from 'vue';
import Vuex from 'vuex'
Vue.use(Vuex)

var app = new Vue({
  el: '#app',
  store,
  components: { A, B, C },
})

The above code makes child components to be able to get the global Vuex Store like this,

//Increment
 this.$store.state.count++;
//Decrement
 this.$store.state.count--;
//Reset
 this.$store.state.count=0;





Get State by computed property

We can get the State by computed property,

computed: {
    count () {
      return this.$store.state.count;
     
      //Or by importing the singleton vuex store
      //return store.state.count
    }
}


However, Vuex has defined mapState helper to have a more graceful writing and avoid repetitive and verbose computed properties.

computed: mapState({
    count: state => state.count, //Assign the computed prop: count, as state.count
    countAlias: 'count', //Optional: assign the other computed prop: countAlias, which is as same as "count"
   
    //Also can declare the computed variable as function
    nextCount(state) {
        return state.count + STEP;
    },
    previousCount(state){
        return state.count - STEP;
    }
})

Notice that mapState(…) returns Object. In order to combine with the local computed properties, we use object rest/spread operator as following,

computed: {
    currentDatetime() { //This is a local computed prop for sample
      return new Date();
    },
    // mix mapState by object spread operator
    ...mapState({
      count: state => state.count,
      countAlias: "count",
      nextCount(state) {
        return state.count + STEP;
      },
      previousCount(state) {
        return state.count - STEP;
      }
    })
  },


Then we can use the computed props in mapState,

console.log('current: ' + this.count);
console.log('next: ' + this.nextCount);
console.log('previous: ' + this.previousCount);




Reference









沒有留言:

張貼留言