美文网首页Vue笔记
Vuex 学习笔记

Vuex 学习笔记

作者: 许小花花 | 来源:发表于2018-07-16 14:56 被阅读19次

    概要

    官方解释Vuex是一个专为Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。状态?我把它理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态。简单的说就是data中需要共用的属性。比如:我们有几个页面要显示用户名称和用户等级,或者显示用户的地理位置。如果我们不把这些属性设置为状态,那每个页面遇到后,都会到服务器进行查找计算,返回后再显示。在中大型项目中会有很多共用的数据,所以尤大神给我们提供了vuex。
    在一些应用比较复杂的单页面项目里使用vuex比较合适,因为当兄弟、父子组件数据通信、共用状态过多时这些状态会变得让你难以管理,当某部分出现问题便要用大量时间去组件中查改代码,这并不是我们开发者想要的,因此用一个vuex来集中管理各个状态是比较好的选择。
    每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

    • 1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
    • 2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

    使用

    一、创建
    • 1.下载 npm install vuex -s
      1. 引入安装与使用
    // main.js
    import Vue form 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex);
    var store = new Vuex.Store({  //store对象
        state:{
            show:false
        }
    })
    new Vue({
      el: '#app',
      data(){},
      router,
      store,  //使用store
      render: h => h(App) 
    })
    

    这是最直接的 vuex 的使用,为了方便 , 我们把 store 对象写在了 main.js 里面 , 但实际上为了便于日后的维护 , 我们分开写更好 , 我们在 src 目录下 , 新建一个 store 文件夹 , 然后在里面新建一个 index.js

    // store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex);
    
    export default new Vuex.Store({
        state:{
            show:false
        }
    })
    

    此时,main.js 就应该写成这样

    // main.js
    import store from './store'
    import Vue from 'vue'
    new Vue({
      el: '#app',
      data(){},
      router,
      store,  //使用store
      render: h => h(App) 
    })
    

    此时,所有的子组件可以通过 $store.state.show 来调用状态值 show
    这样就把 store 分离出去了 , 那么还有一个问题是 : 这里 $store.state.show 无论哪个组件都可以使用 , 那组件多了之后 , 状态也多了 , 这么多状态都堆在 store 文件夹下的 index.js 不好维护怎么办 ? 使用 vuex 的 modules
    我们把其作为一个状态文件分离出去

    //  components/dialog_store.js
    export default {
        state:{
            show:false
        }
    }
    

    再把 store 文件夹下的 index.js 改成 :

    import Vue from 'vue'
    import vuex from 'vuex'
    Vue.use(vuex);
    
    import dialog_store from '../components/dialog_store.js';   //引入某个store对象
    
    export default new vuex.Store({
        modules: {
            dialog: dialog_store
        }
    })
    

    这时,在组件需要使用这个状态时,把使用方法 this.$store.state.show 改写为 this.$store.state.dialog.show 即可。
    如果还有其他的组件需要使用 vuex , 就新建一个对应的状态文件 , 然后将他们加入 store 文件夹下的 index.js 文件中的 modules 中。

    modules: {
        dialog: dialog_store,
        other: other,  //其他组件
    }
    
    二、访问

    上面我们已经创建好了const state ,这个就是我们说的访问状态对象,它就是我们SPA(单页应用程序)中的共享值。现在我们要把这个const state 赋值给内部对象,也就是把 components/dialog_store.js 中的值赋值给我们模板里data中的值。

    • 1.通过computed的计算属性直接赋值
    computed:{
        show(){
            return this.$store.state.dialog.show
        }
    }
    
    • 2.通过mapState的对象来赋值
    <template>
      <el-dialog :visible.sync="show"></el-dialog>
    </template>
    
    <script>
    import {mapState} from 'vuex';
    export default {
      computed:{
    
        //这里的三点叫做 : 扩展运算符
        ...mapState({
          show:state=>state.dialog.show
        }),
      }
    }
    </script>
    

    相当于

    <template>
      <el-dialog :visible.sync="show"></el-dialog>
    </template>
    
    <script>
    import {mapState} from 'vuex';
    export default {
      computed:{
        show(){
            return this.$store.state.dialog.show;
        }
      }
    }
    </script>
    
    • 3.通过mapState的数组来赋值
    computed:mapState(["show"])
    
    三、修改状态 (Mutations)

    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

    // components/dialog_store.js
    export default {
        state:{//state
            show:false
        },
        mutations:{
            switch_dialog(state){//这里的state对应着上面这个state
                state.show = state.show?false:true;
                //你还可以在这里执行其他的操作改变state
            }
        }
    }
    

    而使用的组件则是通过 $store.commit 方法来修改状态,像下面这样使用 $store.commit('switch_dialog') 来触发 mutations 中的 switch_dialog 方法。

    <template>
      <div id="app">
        <a href="javascript:;" @click="$store.commit('switch_dialog')">点击</a>
        <t-dialog></t-dialog>
      </div>
    </template>
    
    <script>
    import dialog from './components/dialog.vue'
    export default {
      components:{
        "t-dialog":dialog
      }
    }
    </script>
    

    这里需要注意的是:

    • 1.mutations 中的方法是不分组件的 , 假如你在 dialog_stroe.js 文件中的定义了 switch_dialog 方法 , 在其他文件中的一个 switch_dialog 方法 , 那么 $store.commit('switch_dialog') 会执行所有的 switch_dialog 方法。
    • 2.mutations里的操作必须是同步的。
    三、执行多个 mutations(action)

    多个 state 的操作 , 使用 mutations 会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用 action 了:

    export default {
        state:{   //state
            show:false
        },
        mutations:{
            switch_dialog(state){   //这里的state对应着上面这个state
                state.show = state.show?false:true;
                //你还可以在这里执行其他的操作改变state
            }
        },
        actions:{
            switch_dialog(context){   //这里的context和我们使用的$store拥有相同的对象和方法
                context.commit('switch_dialog');
                //你还可以在这里触发其他的mutations方法
            },
        }
    }
    

    也就是说,在一个 action 中可以一次执行多个 mutation 。这时,我们用 $store.dispatch 来触发 action 中的方法。官方推荐 , 将异步操作放在 action 中。

    <template>
      <div id="app">
        <a href="javascript:;" @click="$store.dispatch('switch_dialog')">点击</a>
        <t-dialog></t-dialog>
      </div>
    </template>
    
    <script>
    import dialog from './components/dialog.vue'
    export default {
      components:{
        "t-dialog":dialog
      }
    }
    </script>
    
    四、getters

    gettersvue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。
    假如我们需要一个与状态 show 刚好相反的状态 ,在使用时可以直接用 computed 这样算出来 :

    computed(){
        not_show(){
            return !this.$store.state.dialog.show;
        }
    }
    

    如果很多很多个组件中都需要用到这个与 show 刚好相反的状态 , 那么我们每次使用都要在组件里写 not_show , 很冗余,使用 getters 就可以解决这种问题 :

    export default {
        state:{   //state
            show:false
        },
        getters:{
            not_show(state){   //这里的state对应着上面这个state
                return !state.show;
            }
        },
        mutations:{
            switch_dialog(state){   //这里的state对应着上面这个state
                state.show = state.show?false:true;
                //你还可以在这里执行其他的操作改变state
            }
        },
        actions:{
            switch_dialog(context){   //这里的context和我们使用的$store拥有相同的对象和方法
                context.commit('switch_dialog');
                //你还可以在这里触发其他的mutations方法
            },
        }
    }
    

    这样,在使用时,直接在组件中使用 $store.state.dialog.show 来获得状态 show , 使用
    $store.getters.not_show 来获得状态 not_show

    参考文章

    vuex最简单、最详细的入门文档
    技术胖博客-Vuex

    相关文章

      网友评论

        本文标题:Vuex 学习笔记

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