State
1.state中的数据,组件中如何获取
this.$store.state.xxx属性
2.mapState辅助函数
1.引入mapState
import {mapState} from 'vuex'
2.在computed计算属性中使用
export default{
computed:mapState(
['count']
)
}
3.计算属性,使用了mapState作为辅助函数,其他计算属性怎么写?
//mapState 函数返回的是一个对象
//ES6 对象展开运算符...mapState(['count'])
export default{
computed:{
...mapState(['count']),//一起使用时,ES6使用对象展开运算符此对象混入到外部对象中
message(){//其他计算属性
return xxxx;
}
}
}
Getter
1.store.js中的getters,组件中如何获取?
this.$store.getters.xxxx(getters名称)
2.store.js中的getters,如何接收多个参数?
//state作为第一个参数接收,(id,name)作为其他两个参数接收,也可以接收一个对象
getters:{
increMethod:(state)=>(id,name)=>{
console.log(id)
if(id<1){
if(name === 'lucy'){
return state.count ++;
}else{
return 'not lucy';
}
}else{
return 88;
}
}
}
//在组件中使用
export default({
computed:{
xxx(){
return this.$store.getters.increMethod(0,'ll'); //这么加参数
}
}
})
//辅助函数mapGetters加参数
待继续研究
3.mapGetters辅助函数
1.引入mapGetters
import {mapGetters} from 'vuex'
2.其他操作与mapState辅助属性类似,此处不再过多描述
4.计算属性,使用了mapGetters作为辅助函数,其他计算属性怎么写
与mapState辅助属性类似,此处也不再过多描述
Mutations
1.store.js中的mutations,组件中如何执行?
//1.普通执行
this.$store.commit('xxx');//xxx指mutations名称
//2.如果有对象形式的参数时(此处对应下面2中mutaions接收对象情况使用)
this.$store.commit({
type:'increment',
num:10
})
2.在store.js中编写mutations,可以接收多个参数,也可以接收对象
//接收多个参数
mutations:{
increment(state,n){
state.count += n;
}
}
//接收对象
mutations:{
increment(state,obj){
state.count += obj.num;
}
}
3.使用常量替代 Mutation 事件类型
1.为什么要用常量替代Mutation事件?
可以将所有的Mutation事件,写入到一个单独的文件中,然后通过常量来替代,可以方便开发者对项目中所有Mutation
事件一目了然
2.如何使用常量来替代?
1.创建一个单独文件mutation_type.js
2.在js中定义常量信息
export const SOME_MUTATION = 'SOME_MUTATION'
3.在store.js中,通过import引入
import {SOME_MUTATION} from './mutation_type.js'
4.常量在mutations中如何使用
mutations:{
[SOME_MUTATION] (state){
//这就是使用常量替代Mutation
}
}
4.如何在组件中执行Mutation方法(mapMutations辅助函数的使用)
1.普通执行
this.$store.commit('xxx')提交
2.使用mapMutations辅助函数
1.引入mapMutations
import {mapMutations} from 'vuex'
2.在methods方法中使用
export default({
methods:{
...mapMutations:(
['increment']
)
}
})
5.在组件中执行Mutations,能否对mutations的名称进行修改(设置别名)?
store.js中定义的名称为add的mutation方法,但是在组件中,我已经在methods中定义了一个名称为add的方法,这时候就需要用到mapMutations辅助函数来设置一个别名了
//store.js
export default new Vuex.Store({
mutations:{//mutations中定义了一个add方法
add:(state)=>{
state.count ++;
}
}
})
//组件中
export default({
methods:{
add(){...},//组件中,已经存在名称为add的方法
...mapMutations({
increment:'add'//故使用辅助函数,将该方法别名为increment,然后通过increment访问即可,其实就是在访问store.js中的名称为add的mutations方法
})
}
})
//在组件中如何使用呢?
<button @click="increment">mapMutations++</button>
6.store.js中的mutations有多个参数,使用辅助函数能否实现多个参数传递??
//mapMutations辅助函数,也可以传递参数,目前我发现只能传递一个参数,多个参数建议传递一个对象。有待继续研究
//store.js
export default new Vuex.Store({
mutations:{
increment:(state,obj)=>{
console.log(obj.n)
console.log(obj.name)
if(obj.name == 'liu'){
state.count+=obj.n;
}else{
state.count ++;
}
}
}
})
//组件中
export default({
methods:{//二选一
//1.不改别名类型的(此处看不到任何参数信息)
...mapMutations(['increment'])
//2.可以改别名的(此处看不到任何参数信息)
...mapMutations({
add:'increment'
})
}
})
//组件中如何使用呢(直接在后面加参数即可,此处是一个对象参数)
<button @click="increment({n:8,name:'liu'})">mapMutations++++</button>
或者
<button @click="add({n:8,name:'liu'})">mapMutations++++</button>
7.mutations中执行的都是同步事务操作
最好不要再mutations中执行异步操作。如果异步操作数据了,组件在commit 后,数据不能立即改变,而且不知道什么时候会改变。处理异步操作,可在一下的actions中进行。
Actions
1.actions和mutations有什么区别?
①Action 提交的是 mutation,而不是直接变更状态。
②Action 可以包含任意异步操作。
2.store.js中,actions如何编写?
//store.js中,编写一个名称为incrementAction的action
export default new Vuex.Store({
actions:{
incrementAction(context){
context.commit('increment')
}
}
})
//简化代码:我们可以使用ES6参数解构来简化代码(特别是我们需要调用 commit 很多次的时候)
export default new Vuex.Store({
actions:{
incrementAction( {commit}){
commit('increment')
}
}
3.组件中,actions如何来分发mutations?
//有两种方式
1.普通分发
this.$store.dispatch('xxx',{amout:10})
2.对象方式分发
this.$store.dispatch({
type:'xxx',
amount:10
})
4.使用mapActions辅助函数,来分发mutations
mapActions辅助函数的使用方法,与mapMutations类似,即①可以修改名称②可以接收参数信息。可以参考mapMutations
5.组合actions的使用
Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?
①Promise实现
Promise是一种异步方案它有3种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败)。
//使用Promise实现的关闭定时器方案:
export default new Vuex.Store({
actions:{
actionA({state,commit}){
let id = null;
// 异步操作
// 只要调用 resolve(),就会立马调用 then()
const promise = new Promise((resolve,reject)=>{
id = setInterval(()=>{
commit('increment',{n:22,name:'liu'});
if(state.count>100) resolve(state.count); //会跳到then()
if(state.count==99) reject(state.count); //会跳到catch(error)
},1000);
});
promise.then((value)=>{//then()部分
console.log(id);
clearInterval(id);
}).catch((error)=>{//异常处理部分
console.log('fail',error)
})
}
}
})
//Promise 还能这么写
new Promise((resolve, reject) =>{
setTimeout(()=>{
//resolve('Hello Vue');
reject('Hello Error');
},1000)
}).then(data =>{
console.log(data);
}, error =>{
console.log("error");
})
②在组件中,可以这么来使用组合action(可能还有更好的写法,有待研究)
export default({
methods:{
multiAction(){//使用组合action
this.$store.dispatch('actionB').then(()=>{
if(this.count>100){
this.$store.dispatch('actionC').then(()=>{
alert("完毕")
})
}
})
}
})
③在store.js中,使用组合action
export default new Vuex.Store({
actions:{
actionD({state,commit,dispatch}){
let id ;
const promise = new Promise((resolve,reject)=>{
id = setInterval(()=>{
commit('increment',{n:28,name:'liu'});
console.log(state.count);
if(state.count>100){
resolve(state.count);
}
},1000)
});
promise.then((value)=>{
clearInterval(id)
dispatch('actionC');//或者commit('其他的mutations')
console.log("完毕")
})
}
}
})
④使用async/await,组合action
async/await还在进一步了解中,有点疑问,后续会补的
参考:https://vuex.vuejs.org/zh/guide/actions.html
Module
1.如何将单一store.js拆分成多个模块?
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
//切记:子模块是这么定义的,而不是const moduleA = new Vuex.Store({...})
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
2.在模块moduleA/moduleB中,如何获取兄弟节点module/根节点store中的一些属性?
const moduleA ={
actions:{
moduleAAction({state,commit,rootState}){
//state---->为子节点状态,即当前moduleA
//rootState--->即父模块状态,即store
//通过state.count--->来获取模块中的state变量
//通过rootState.count--->来获取父模块中的state变量
console.log('moduleA模块中的count属性值:'+state.count);
console.log('父模块中的hello属性值:'+rootState.hello);
console.log('兄弟模块moduleB中的count属性:'+rootState.moduleB.count);
commit('moduleAIncr');
}
}
}
3.命名空间
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,这样使得多个模块能够对同一 mutation 或 action 作出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced:true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
附:Vue篇目录:
1.Vue组件之间传值问题 2.v-model 用在组件中
3.Vue.js 实战 调查问卷WebApp项目 4.vue-cli + webpack搭建Vue开发环境
5. Vue简单问题汇总(持续更新...) 6.Vue组件之间数据通信之Bus总线
7.Vue-Router导航钩子(附Demo实例) 8.ES6箭头函数与普通函数的区别
9.Vuex的使用 10.Vuex组件中的mapState、mapGetters、mapMutations、mapActions等辅助函数
11.组件中调用Vuex的state,getters,mutations,actions,modules的数据传递、传参问题
12.Vuex命名空间namespaced 13.Vue axios的使用