Vue(十五):Vuex

1、Vuex是个啥
  Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,类似于弄了一个全局的缓存库,缓存库中数据的改变---会实时改变---组件中因为使用该数据而产生的状态,达到一种牵一发而动全身的效果。

2、Vuex的使用
  首先我们需要使用“npm install vuex --save"命令来安装vuex。vuex的核心概念是state、getter、mutation、action、module这五个概念,我们在下面放了一些基础的代码示例,再通过介绍来了解他们。

1)、state
  state相当于组件中的data,以代码示例中的count为例,我们可以通过this.$store.state.count来访问该值,但是值得注意的是我们只能读取,不能直接修改。我们还可以使用mapState辅助函数帮助我们生成计算属性,需要import { mapState } from 'vuex'。举例举例:

computed:mapState({
        count:(state)=>state.count,
        countAlias:'count',
        countAdd2(state){
            return state.count+2;
        },
    }),

2)、getter
  getter相当于组件中的computed,有时候我们需要直接在store中过滤一些数据,我们就可以直接使用getter,且getter中的数据会被缓存。就像在示例代码中写的那样,getter的第一个参数是state,后面的参数我们可以在调用的时候传进去。以代码示例中的nameTodos为例,我们可以通过this.$store.getters.nameTodos来访问该值,我们还可以使用mapGetters辅助函数帮助我们生成计算属性,需要import { mapGetters } from 'vuex'。举例举例:

<span v-for="todo in $store.getters.nameTodos" :key="todo.id">{{todo}}</span><br> //html代码
<span v-for="todo in $store.getters.getTodoById(2)" :key="todo.id">{{todo}}</span><br>
<span v-for="todo in maxNameTodos" :key="todo.id">{{todo}}</span><br>
//vue示例中代码
computed:mapGetters({
        maxNameTodos:'maxNameTodos'
    }),

3)、mutation
  mutation相当于组件中的methods,刚才我们就说过了不能直接更改state中的值,怎么更改呢?就通过mutation中的方法更改。就像在示例代码中写的那样,mutation的第一个参数是state,后面的参数我们可以在调用的时候传进去。以代码示例中的increment为例,我们可以通过this.$store.commit('increment')来访问该方法,我们还可以使用mapMutations辅助函数帮助我们生成计算属性,需要import { mapMutations} from 'vuex'。需要注意的是,mutation中的方法必须是同步的,不能是异步方法。举例举例:

<span>{{$store.state.count}}</span>  //html代码
<button @click="Add1">+1</button>
<button @click="Add2">+10</button>
<button @click="Add3">+2</button>
<button @click="Add4">+1</button>
//vue示例代码
methods:mapMutations({
        Add1(){
            this.$store.commit('increment');
        },
        Add2(){
            this.$store.commit('incrementObj',{count:10});
        },
        Add3(){
            this.$store.commit(Mutations.SOME_MUTATION);
        },
        Add4:'increment',
    }),

4)、action
  刚才我们说了mutation不能是异步操作,那谁来进行呢?action。action不是直接修改state,action也是直接提交的mutation。需要注意的是action的第一个参数是context,它是一个和store具有相同属性和方法的另一个对象,所以他也能调用mutation中的方法。以代码示例中的incrementObj为例,我们可以通过this.$store.dispatch('incrementObj')来访问该方法,我们还可以使用mapActions辅助函数帮助我们生成计算属性,需要import { mapActions} from 'vuex'。举例举例:

<span>{{$store.state.count}}</span> //html代码
<button @click="Add5">+10</button>
<button @click="Add6">+11</button>
//vue示例代码
methods:mapActions({
        Add5(){
            this.$store.dispatch('incrementObj',{count:10}).then((s)=>{alert(s)});
        },
        Add6(){
            this.$store.dispatch('increment12',{count:10});
        }
    }),

5)、代码示例
  首先我们要在src目录下建立store文件夹,然后建立store.js文件

import Vue from "vue";    //store.js
import Vuex from "vuex";
import * as Mutations from '@/store/mutation-types.js'
Vue.use(Vuex);
var store = new Vuex.Store({
    state:{
        count:1,
        todos:[
            {id:1,name:"张三"},
            {id:2,name:"李四"},
            {id:3,name:"王二麻子"},
        ]
    },
    mutations:{
        increment(state){
            state.count++;
        },
        incrementObj(state,obj){
            state.count+=obj.count;
        },
        [Mutations.SOME_MUTATION](state){
            state.count+=2;
        }
    },
    getters:{
        nameTodos:state=>{
            return state.todos.filter(v=>v.id<=1);
        },
        getTodoById:(state)=>(id)=>{
            return state.todos.filter(v=>v.id==id);
        },
        maxNameTodos:state=>{
            return state.todos.filter(v=>v.id>2);
        },
    },
    actions:{
        incrementObj(context,obj){
            return new Promise((resolve, reject)=>{
                setTimeout(() => {
                    context.commit('incrementObj',obj);
                    resolve('success');
                }, 1000);
            })
        },
        increment12(context,obj){
            context.dispatch('incrementObj',obj).then(()=>{
                context.commit('increment');
            });
        },
    },
});

export default store;

 然后在main.js中引入store

import Vue from 'vue'
import App from './App'
import store from './store/store.js'
new Vue({
  el: '#app',
  store,
  components: { App },
  template: '<App/>',
})

6)、module
  vuex允许我们将store分割成模块,这样我们做大型项目的时候容易管理。基本理念呢就是建立一个新的store对象,然后汇总引入到最顶级的store对象中,加在module属性中,就像组件一样。我们下面呢通过动态注册,将vuex的状态同步vue的示例中,获取全局的属性和方法。
首先在store文件夹下建立modules文件夹,然后建立一个TestStore.js。写个简单的代码:

export default {
    state: {
        count: 1,
    },
    getters: {
        store_test_count(state) {
            return state.count
        },
    },
};

然后引入到store.js中,在store对象导出之前,动态注册一下,注册完之后,我们就能全局访问getters中的store-test-count了。代码如下:

import Test from "@/store/modules/Test.js";
store.registerModule("Test", Test);

后面我们在store文件夹下建立mappings文件夹,然后建立一个Test.js,这实际是一个vue的示例。写个简单的代码:

import { mapGetters } from 'vuex'
export default {
    computed: mapGetters([
        'store_test_count',
    ]),
}

这个时候呢,我们的这个js通过获取store中的属性就有了一个叫store-test-count的计算属性。我们把这个属性在main.js中混合到App示例中之后就是全局的计算属性了。我们建立一个引导的js文件,叫storeMapping.js。上代码吧:

import Test from "@/store/mappings/Test.js";   //storeMapping.js
export default {
    initMixins(Vue) {
      Vue.mixin(Test);
    }
  };
//main.js
import storeMapping from './store/storeMapping.js'
storeMapping.initMixins(Vue);  //在创建App示例前调用

  

 

posted @ 2020-06-10 17:41  梁仕博  阅读(135)  评论(0编辑  收藏  举报