对于vuex的基本API去vuex官网上讲的很详细(比vue稍强 哈哈~~)https://vuex.vuejs.org/zh/api/#vuex-store
直接进入正题
目录结构
创建一个store的文件夹,如果项目比较庞大,建议将每个项目所使用到的数据按照模块分出来,将所有的都放在统一的一个文件夹(modules)中。modules文件同级创建一个index,在这index中导入vue,vuex,使用Vuex store 注册store。
index.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import common from './modules/common'
import test from './modules/test'
Vue.use(Vuex)//为vue 添加vuex的功能
export default new Vuex.Store({
modules: {
user,
common,
test
}
})
state:数据仓库
Mutation:改变VueX的state中状态的唯一方法提交mutation
export default {
namespaced: true,
//分模块化管理,为了解决不同模块的命名冲突问题,将不同模块的namespaced:true,之后再不同页面中引入getter,action,mutations的时候,需要加上所属模块的模块名
state: {
name: '张三',
age: 10,
twoName: '张三'
},
mutations: {
// 第一个参数是state,第二个参数是传递的参数
updateName(state, data) {
state.name = data.name;
},
updateAge(state, data) {
state.age = data.age
}
},
}
// test.vue
<template>
<div>
<span>{{age}}</span>
<button @click="addAge">++增加++</button>
</div>
</template>
<script>
export default {
methods: {
addAge() {
//这里的commit只能传递两个参数,参数1:path,参数2:object
this.$store.commit("test/updateAge", {
age: this.age + 1
});
}
},
// computed具有缓存的功能
computed: {
age() {
return this.$store.state.test.age;
},
}
};
</script>
Mutation 必须是同步函数?
<template>
<div>
<span>{{age}}</span>
<button @click="addAge">++增加++</button>
</div>
</template>
<script>
export default {
methods: {
addAge() {
//这里的commit只能传递两个参数,参数1:type,参数2:object
this.$store.commit("test/updateAge", {
age: this.age + 1
});
}
},
};
</script>
当我们点击一次增加按钮之后,我们发现mutation中的age变化了,但是state中的age没有变化,当我们第二次点击的时候state中更新的是上一次的age,但是mutataion中的还是罪行的age。
引用官网的解说:我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。所以这里出现了延迟,也就是说用了异步回掉函数操作数据,数据的状态改变是不可追踪的。 注意:状态并不是不会生效,而是不可追踪。
当我们多次操作的时候,如果出现报错的情况,我们参考的数据是有问题的,就会造成我们调试的时候误判。
actions:异步状态更新
mutation只能进行同步的状态更新,当我们要使用异步的状态更新的时候我们就需要用到actions,Action使用的时候是直接提交一个commit到mutations中,所以最终的更新状态也是在mutations中进行的。
export default {
namespaced: true,
state: {
name: '张三',
age: 10,
twoName: '张三'
},
mutations: {
// 第一个参数是state,第二个参数是传递的参数
updateName(state, data) {
state.name = data.name;
},
updateAge(state, data) {
state.age = data.age
}
},
actions: {
changeName(context, data) {
setTimeout(() => {
context.commit('updateName', {
name: data.name
})
}, 1000);
},
changeAge(context, data) {
setTimeout(() => {
context.commit('updateAge', {
age: data.age
})
}, 1000);
}
},
}
// test.vue
<template>
<div>
<span>{{age}}</span>
<button @click="addAge">++增加++</button>
</div>
</template>
<script>
export default {
methods: {
addAge() {
this.$store.dispatch("test/changeAge", {
age: this.age + 1
});
}
},
computed: {
name() {
return this.$store.state.test.name;
},
age() {
return this.$store.state.test.age;
},
}
};
</script>
getters
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
export default {
namespaced: true,
//分模块化管理,为了解决不同模块的命名冲突问题,将不同模块的namespaced:true,之后再不同页面中引入getter,action,mutations的时候,需要加上所属模块的模块名
state: {
name: '张三',
age: 10,
twoName: '张三'
},
// 和computed一样,带有缓存,以来对象变换的时候会重新计算
getters: {
twoName(state) {
let statusText = '失恋了'
if (state.name === '张三') {
return state.name + statusText
}
}
}
}
// test.vue
<template>
<div>
<span>{{twoName}}</span>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters('test',['twoName'])
}
};
</script>
辅助函数
当我们需要操作的数据或者方法很多的时候是可以使用辅助函数。
// test.js 文件
export default {
namespaced: true,
//分模块化管理,为了解决不同模块的命名冲突问题,将不同模块的namespaced:true,之后再不同页面中引入getter,action,mutations的时候,需要加上所属模块的模块名
state: {
name: '张三',
age: 18,
msg: ''
},
mutations: {
updataName(state, data) {
state.name = data.name;
},
updataAge(state, data) {
state.age = data.age;
}
},
actions: {
changeAge(context, data) {
context.commit('updataAge', {
...data
});
}
},
// 和computed一样,带有缓存,以来对象变换的时候会重新计算
getters: {
msg(state) {
return state.name + state.age
}
}
}
// test.vue 文件
<template>
<div>
<div>{{name}}</div>
<div>{{age}}</div>
<div>{{msg}}</div>
<button @click="handleName">改名</button>
<button @click="handleAge">该年龄</button>
</div>
</template>
<script>
import { mapActions, mapState, mapMutations, mapGetters } from "vuex";
export default {
computed: {
...mapState({
name: state => state.test.name,
age: state => state.test.age,
msg: state => state.test.msg
}),
...mapGetters("test", ["msg"])
},
methods: {
...mapMutations("test", ["updataName"]),
...mapActions("test", ["changeAge"]),
handleName() {
this.updataName({ name: "李四" });
},
handleAge() {
this.changeAge({ age: 99 });
}
}
};
</script>