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

浙公网安备 33010602011771号