VUEX 详解

作者: _cxrs_ | 来源:发表于2020-09-16 16:31 被阅读0次

    为什么使用vuex

    在中大型应用中,应用的各个组件间需要进行数据传递,使用传统方式繁琐且不可控

    Vuex 为所有组件提供集中式的可追踪的状态(数据) 管理

    vuex 的数据是响应式的

    使用Vuex将摒弃传统的 event emmit 和props的方式进行数据的传递和更新

    问题场景

    问题一、通过路由传参数,我们会采用params 或者query形式 ,但是这两种方式都会在URL上做手脚 , 如果传递参数过多,会导致400 Bad Request (如,点击表格某行,携带行数据跳转到新页面进行查看)

    问题二、兄弟传值

    问题三、多个地方使用同一数据,为减少重复请求数量

    由于要下钻的ID过长,受浏览器的URL长度限制问题 可以使用Vuex做中间过渡,跳转前存储ID信息,进入B页面后从Vuex获取ID信息。

    注意: vuex 存储的数据是在内存中的 页面刷新 数据就会消失

    每次调用mutation之后向 localstorage 存值,防止刷新丢失

    VUEX 具体用法

    创建 VUEX

    在 uni-app 项目根目录下新建 store 目录,在 store 目录下创建 index.js 定义状态值。

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
     const  store  = new Vuex.Store({
        state:{
            firstData:''
        },
        getters:{
            get(state){
                return state.firstData
            }
        },
        mutations:{
            add(state,data){
                state.firstData =state.firstData + data
            }
        },
        actions:{
            jian({commit,state},name){
                commit('add',name)
            }
        }
    })
    
    export default  store
    
    

    在 main.js 中挂载

    Vue.prototype.$store = store 
    const app = new Vue({
        ...App ,
        ...store 
        
    })
    

    VUEX属性解析

    1、组件Vue Component通过dispatch来调用actions提供的方法
    2、而actions除了可以和api打交道外,还可以通过commit来调mutations提供的方法
    3、最后mutaions将数据保存到state中
    4、当然,Vue Components还以通过getters提供的方法获取state中的数据
    

    VUX数据的使用

    mutations

    组件页面中的 可以通过 this.$store.dispatch('jian',2) 调用

    state:{
            firstData:1
        },
    mutations:{
            add(state,data){
                state.firstData =state.firstData + data
            }
        },
        actions:{
            jian({commit,state},name){   // 把commit 解构出来
                commit('add',name)
            }
        }
    

    commit

    组件页面中的可以通过 this.$store.commit("add",3);

    mutations:{
            add(state,data){
                state.firstData =state.firstData + data
            }
        },
    

    getters

    组件可以通过 this.$store.getters.get

    getters:{
            get(state){
                return state.firstData
            }
        },
    

    VUEX 的高级用法

    一定要引入 vuex 并且要在开头调用 Vue.use(Vuex)

    下面四个方法均是在App组件中想要获得数据或方法

    mapState

    将状态从根组件“注入”到每一个子组件中

    在 store 中添加一个数据

    state: {
        counter: 1,          
    }
    复制代码
    

    在App组件中使用这个数据

    • 可以使用 this.$store.state.counter 获得这个数据,但是我们一般不用此方法
    • 我们可以使用mapState

    在App中导入这个方法

    import {mapState} from "vuex"
    

    然后在计算属性中(computed)使用

    computed:{
        ...mapState(["counter"]),    //  映射 this.count 为 store.state.count   使用对象展开运算符将此对象混入到外部对象中
    }
    复制代码
    

    这样就获得了这个数据,可以在页面中使用 插值表达式:{{ counter }},直接使用这个数据

    如果想要获得多个数据(数组也可以)

    ...mapState(["counter","arr","list"]),
    

    只需中间加个逗号,这样写就ok了

    mapGetters

    有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数,这时就要用到 mapGetters 方法了

    例如我在 store 中定义一个数组

    state: {
        list: [
          { name: "ming", score: 40 },
          { name: "gang", score: 50 },
          { name: "lan", score: 60 },
          { name: "mei", score: 70 },
          { name: "tian", score: 80 },
          { name: "bai", score: 90 },
        ]
    }
    复制代码
    

    想要过滤出分数小于60分的,这时就需要在 store 中的 getters 中定义一个方法:

    getters: {
        faileNum(state){
          return state.list.filter(item=>item.score < 60).length;
        }
    }
    复制代码
    

    然后在App组件的计算属性中接收此方法
    一定不要忘了引入

    import {mapGetters} from "vuex"
    computed:{
        ...mapGetters(["faileNum"]),    // 使用对象展开运算符将 getter 混入 computed 对象中
      }
    复制代码
    

    然后直接在组件中使用插值表达式输出就好了

    <p>不及格的学生人数是:{{faileNum}}</p>

    mapMutation

    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

    例如:我们在 store 中定义一个数据

    state: {
        stus: ["ming", "hong"],
      }
    复制代码
    

    我们想要在stus数组中加入一个数据

    除了平常用的 this.$store.commit(xxx) ,我们最经常使用的还是 mapMutation 方法

    此时我们就需要在store中的 mutations 下定义一个方法

     mutations: {
        add(state, n) {
          state.stus.push(n)
        },
      }
    复制代码
    

    然后直接在 App组件中导入这个方法

    import {mapMutations} from "vuex"

    然后在methods下使用这个方法,如下

    methods:{
        ...mapMutations(["add"]),   // 将 `this.add()` 映射为 `this.$store.commit('add')`
      }
        //// `mapMutations` 也支持载荷:
          'add' // 将 `this.add(amount)` 映射为 `this.$store.commit('add', amount)`
    
    

    最后直接在组件中 绑定click方法使用 就好了,还可以传参

    <button @click="add('tian')">增加</button>
    复制代码
    

    注:Mutation 必须是同步函数

    mapActions

    Action 类似于 mutation,不同在于:

    • Action 提交的是 mutation,而不是直接变更状态
    • Action 可以包含任意异步操作。

    例如,我们写一个异步操作,首先在 store 中定义数据

     state: {
        counter: 1,
      }
    复制代码
    

    然后在 mutations 中定义一个方法

    mutations: {
        //同步点击
        add(state) {
          state.counter++
        }
      },
    复制代码
    

    最后在 actions 中定义一个异步操作

    actions: {
        // 如果把异步放在mutaions中,使用程序在调试面板中很难调试,可以把异步放到actions
        // actions和mutations中不同之处在于:
        // action提交也是mutations,不能直接修改状态
        // actions可以包含任意的异步操作
        // actions函数接收一个与store实例具有相同方法的属性的context属性,可以通过context.commit提交,也可以通过context.state获取state
       // addAsyncNum(context){
         // setTimeout(function(){
          //  context.commit("addNum")
          //},2000)
        //},
        jian({commit,state},name){
                commit('add',name)
            }
      }
    复制代码
    

    接着在 App组件中导入

    import {mapActions} from "vuex"

    然后在方法中使用

    methods:{
        ...mapActions(["jian"])
      }
    // 'jian', // 将 `this.increment()` 映射为 `this.$store.dispatch('jian')`
    
          // `mapActions` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('jian', amount)`
    

    最后在App组件中绑定方法使用就ok了

    <button @click="addAsyncNum">异步点击</button>
    

    相关文章

      网友评论

        本文标题:VUEX 详解

        本文链接:https://www.haomeiwen.com/subject/rhkhyktx.html