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示例前调用