VueX数据管理工具

vuex是一个状态(数据)管理工具,它能够完成组件之间的数据共享(组件的通信)。

一.vuex的作用        

        1、vuex能够保存全局数据(数据仓库),供整个应用使用

        2、vuex保存的数据是响应式的

        3、vuex保存的数据可以跟踪状态的变化

二.vuex的核心概念(创建vuex.store对象里的配置项)

        state : 数据仓库 ,存储所有的 共享数据 ,相当于vue组件里的data。

        Getter : 在state的基础上 派生的数据, 相当于vue组件里 computed。

        Mutation:修改state的数据时,用mutation,这与跟踪状态 有关系,只能有同步代码。

        Action:解决mutation里只能有同步代码的问题,action里可以有异步代码。

        modules:模块化。

 三.vuex的基本使用

        ①安装

npm安装vueX:  npm install vuex --save

        ②创建vuex对象

./src/store/index.js

import Vue  from 'vue'
//引入vueX
import Vuex from 'vuex'
//把vueX安装到Vue里
Vue.use(Vuex)

export default new Vuex.Store({
    state:{
          id: '01'
    },
    getters:{},
    mutations:{},
    actions:{}
})

        ③把vuex.store对象植入到 vue的根属性

./src/main.js

import store from './store'

new Vue({
  	el: '#app',
  	store,//把store对象植入到vue的根属性,在vue组件里就可以使用 this.$store拿到vueX.store对象
    router
  		……………………	
})

        ④组件里获取数据

//模板里:
$store.state.id
//脚本里
this.$store.state.id

        ⑤组件里保存数据

this.$store.state.id = '02' 
//这个方式虽然可以,但是不推荐,因为,它不能跟踪状态。
//推荐,强烈推荐(必须)使用mutation来修改数据。

四:vuex的核心概念详解

        state:数据仓库 ,存储所有的 共享数据 ,相当于vue组件里的data,是一个单一状态树

        使用: 在组件中使用:this.$store.state.属性名。

         示例:

export default new VueX.Store({
    state:{
        age:12,
        isAdult:"未成年",
        isAllowMarry:false
    }
    …………………………
});

        组件里获取:

{{$store.state.age}}
{{$store.state.isAdult}}
{{$store.state.isAllowMarry?"可以结婚了":"不要着急,再等等"}}

         Getter : 在state的基础上 派生的数据, 相当于vue组件里 computed

         示例:

export default new VueX.Store({
    state:{
        age:12,
        isAdult:"未成年",
        isAllowMarry:false
    },
    getters:{
       // state:就是仓库的state,不用程序员处理,vuex已经处理好了 
        ageChina:function(state){
            let shi = parseInt(state.age/10); //1
            let ge = state.age%10;//2
            let str = "";
            switch(shi){
                case 1:str='一';break;
                case 2:str='二';break;
            }
            str+='十'
            switch(ge){
                case 1:str+='一';break;
                case 2:str+='二';break;
                case 3:str+='三';break;
                case 4:str+='四';break;
                case 5:str+='五';break;
                case 6:str+='六';break;
                case 7:str+='七';break;
                case 8:str+='八';break;
                case 9:str+='九';break;
            }
            return str+'岁';
        }
    },
    …………………………
});

        组件里获取:

{{$store.getters.ageChina}}

        Mutation:修改state的数据时,用mutation,这与跟踪状态 有关系。

        换句话说,在vuex中,对mutation的定义(定位)是:修改状态的,即:在mutation提交的前后,状态应该是不一样的。当然了,也会在vue的dev-tools工具中看到跟踪状态的效果。

        在vuex中,强烈建议(必须)使用mutation改变state中的值。可以在vuex对象中使用严格模式来检测: const store = new Vuex.Store({ strict: true })

        示例: 

export default new VueX.Store({
    state:{
        age:12,
        isAdult:"未成年",
        isAllowMarry:false
    },
    getters:{
        ageChina:function(state){
            let shi = parseInt(state.age/10); //1
            let ge = state.age%10;//2
            let str = "";
            switch(shi){
                case 1:str='一';break;
                case 2:str='二';break;
            }
            str+='十'
            switch(ge){
                case 1:str+='一';break;
                case 2:str+='二';break;
                case 3:str+='三';break;
                case 4:str+='四';break;
                case 5:str+='五';break;
                case 6:str+='六';break;
                case 7:str+='七';break;
                case 8:str+='八';break;
                case 9:str+='九';break;
            }
            return str+'岁';
        }
    },
    // mutations:是跟踪状态。这里面只能有同步代码,这是必须的。
    mutations:{
    //    incAge(state,num){
    //        state.age+=num;
        //state:就是store对象里的state,不用程序员传入
        //payload:就是形参,叫作载荷
        incAge(state,payload){
            
            state.age+=payload.num;
            
           if(state.age>=18){
              state.isAdult = "已成年";
           }else{
              state.isAdult = "未成年";
           }
           if(state.age>=22){
               state.isAllowMarry = true;
           }else{
               state.isAllowMarry = false;
           }
       }
    },
   …………………………………………
});

        提交mutation:

//组件里提交
this.$store.commit('incAge',num);

//action提交
incAge(context,num){
     context.commit('incAge',num);
}

       Action:解决mutation里只能有同步代码的问题,action里可以有异步代码

       Action 类似于 mutation,不同在于:

                ​ Action 提交的是 mutation,而不是直接变更状态。

                 ​ Action 可以包含任意异步操作。

        示例: 

export default new VueX.Store({
    state:{
        age:12,
        isAdult:"未成年",
        isAllowMarry:false
    },
    getters:{
        ageChina:state=>{
            let shi = parseInt(state.age/10); //1
            let ge = state.age%10;//2
            let str = "";
            switch(shi){
                case 1:str='一';break;
                case 2:str='二';break;
            }
            str+='十'
            switch(ge){
                case 1:str+='一';break;
                case 2:str+='二';break;
                case 3:str+='三';break;
                case 4:str+='四';break;
                case 5:str+='五';break;
            }
            return str+'岁';
        }
    },
    // mutations:是跟踪状态。这里面只能有同步代码,这是必须的。
    mutations:{
    //    incAge(state,num){
    //        state.age+=num;
        incAge(state,payload){
            state.age+=payload.num;
           if(state.age>=18){
              state.isAdult = "已成年";
           }else{
              state.isAdult = "未成年";
           }
           if(state.age>=22){
               state.isAllowMarry = true;
           }else{
               state.isAllowMarry = false;
           }
       }
    },
    // 如果出现异步操作,就需要使用action,action不是必须的。
    actions:{
    //    incAge(context,num){
    //        context.commit('incAge',num);
    //    }
        // incAge(context,payload){
        //     context.commit('incAge',payload);
        // }
        //context:是store对象
        incAge(context,payload){
            // context.commit('incAge',payload);
            context.commit(payload);
        }
    }
});

        Action和mutation的区别:

                在代码的角度上,action是来提交mutation的

                在用途(意义)上:区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化。 vuex 真正限制你的只有 mutation 必须是同步的这一点。 当然actions可以包含任何异步操作,如果程序员自己想处理异步操作,也可以不使用actions。

         Modules:当项目比较大时,所有的全局数据存放在state里,会非常混乱,怎么办?使用module,把数据分门别类的进行处理,即:模块化。

         每个模块是一个独立的store。然后由总体的store引入所有的分模块store。

        如下:两个模块分别管理不同类型的数据

./src/store/moduleA.js
export default {
	state: {count:1}, 
    mutations: { ... }, 
    actions: { 
         incCount(context){
            console.log("moduleA的action");
            setTimeout(()=>{
                context.commit("incCount");
            },2000);
        }
    }, 
    getters: { ... } 
}
                                                   
./src/store/moduleB.js
export default {
	state: {age:2}, 
    mutations: { ... }, 
    actions: { 
         incCount(context){
            console.log("moduleB的action");
            setTimeout(()=>{
                context.commit("incCount");
            },2000);
        }
    }, 
    getters: { ... } 
}

         在总的store里包含所有的模块:

./src/store/index.js

import Vue from "vue";
import vueX from "vuex";
import moduleA from "./moduleA";
import moduleB from "./moduleB";

Vue.use(vueX);

export default new vueX.Store({
    modules:{
        moduleA:moduleA,
        moduleB:moduleB
    }
    //简写:
    modules:{
        moduleA,moduleB
    }
});

         组件里使用数据时,多加个模块名即可,如:

$store.state.moduleA.count // -> moduleA 的状态
$store.state.moduleB.count // -> moduleB 的状态

        注: 组件里派发action(或者提交mutation)时,如果,直接写action(mutation)的名字,那么就会找到所有同名的action(mutation)。(getter也有这个问题)

//如:
//在组件内容,派发action
this.$store.dispatch({
          type:"incCount"
        });
那么就会,派发给moduleA和moduleB里的incCount。即:moduleA和moduleB里的incCount都被执行了。如果不希望这样,那就用命名空间

        模块(Module)里的命名空间(namespaced:true)。

        默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

        如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

         1)、模块定义时,加上namespaced:true

export default {
    namespaced:true,
    state:{
        count:1
    },
    mutations:{
       ……………………
    },
    actions:{        
        incCount(context){
            console.log("moduleA的action");
            setTimeout(()=>{
                context.commit("incCount");
            },2000);
        }
    }
}

         2)、组件里派发action时,加上模块名

this.$store.dispatch('moduleA/incCount');

五:vuex的 数据流转

        

        解读一下: vue组件 派发(dispatch)action。action里提交(commit)mutation,mutation里修改(mutate)state的数据,state的数修改后,会响应式渲染到模板上。  

六:vuex的辅助函数

        1.mapState 

         当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:

         mapState辅助函数会把仓库中的状态映射到组件的computed上。

//1、vueX
export default new vueX.Store({
   state:{
       count:10
   }
})

//2、组件里
import { mapState } from "vuex";

export default {
  name: "Store01",
  data() {
    return {};
  },
  //1)、把vueX中的state用计算属性,很麻烦
//   computed:{
//       count(){
//           return this.$store.state.count
//       }
//  },
//  2)、使用mapState(不能再写其它计算属性)
//   computed: mapState({
//     // 箭头函数可使代码更简练
//     count: state => state.count,
//   }),
//  3)、使用mapState继续简写(不能再写其它计算属性)
//   computed: mapState(['count']),
//  4)、使用mapState,这样写
    computed:{        
        ...mapState(['count']),
        a:function(){
            return 250;
        },
    }
};

                mapState映射模块里的数据,: 

//直接把整个模块映射过来

//1、计算属性里的映射
computed:{        
    ...mapState([模块名]),        
},
    
//2、模板上的使用

<p>{{模块名.属性}}</p>

        2.mapGetters

         mapGetters辅助函数,把仓库中的getters映射到组件的computed里。

computed: {
    ...mapState(["count", "age", "isAdult"]),
    ...mapGetters(["ageChina"]),

  },

          mapGetters映射模块里的数据 :

computed:{        
        ...mapGetters({"属性名":"模块名/属性名"}),        
        ...mapGetters({"money":"a/money"}),
 },

        3.mapMutations

           在methods里映射

       4.mapActions  

          在methods里映射

 methods: {
    ...mapMutations(["incAge1"]),
    ...mapActions(["incAge"]),
 }

         mapMutations映射模块里的方法(mapActions是同样的道理)  

methods:{
    ...mapMutations({"方法名":"模块名/mutation名字"}),
    ...mapMutations({"addBook":"a/addBook"}),
}

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小可乐吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值