【二十】vuex

64 阅读3分钟

前言

本篇博客主要回顾了vuex的相关操作。

面试回答

1.vuex:Vuex主要包含了state、getters、actions、mutations。按照日常使用,我们需要创建一个store类,store类分成两部分,一部分是构造函数,另外一部分是commit和dispatch方法。构造函数的主要工作是赋值以及响应式的处理,首先要对拿到的参数进行解构,分为state、getters、actions、mutations。然后把state和getters设置成响应式,这里实现响应式的方法可以用vue.observable或者用object.defineProperty设置get去实现,而getters需要先进行遍历。在这之后保存一下mutations和actions。接下来就是commit和dispatch的实现,这里简单一些,直接用传入的参数配合保存下来的mutations或者actions去执行对应的函数即可,当然因为state是单一数据源,如果要考虑mutations必须是同步任务,这里也可以对mutations的参数添加限制。最后vuex是通过vue.use进行注入,那么就需要提供一个install方法,在install方法中通过mixin以及beforeCreate生命周期将store注入vue实例组件。

知识点

Vuex 是一个专为Vue.js开发的状态管理模式。

1.state(数据中心)

单个数据:组件通过this.$store.state访问到所需数据

多个数据:mapState辅助函数,返回的是一个对象,通过展开运算符与其他数据进行混合

mapState({
    count: state => state.count,
        //传字符串参数'count'等同于state=>state.count
            countAlias:'count',
                //为了能够使用this获取局部状态,必须使用常规函数,也可以进行数据的计算
                    countPlusLocalState(state){
                            return state.count + this.localCount
                                }
                                })

本质上,可以通过$store.state.count++来改变count的值,之所以必须通过mutation改变store的值,是为了能被devTools监听记录,否则store被修改也不知道在哪被改的,如果遇到多处修改count,那么不易调试。

2.Getter

从state派生的数据,store中对数据进行计算处理的公共方法,相当于state的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  • store内

    ...action:{},
                                    getters:{
                                      countDoneTodos(state){
                                          return state.count * 5
                                            },
                                              countLength(state,getters){
                                                  return getters.countDoneTodos.length
                                                    }
                                                    }
    
                                                //store.getters.countLength</code></pre></li><li><p>组件内</p><pre><code>export default {
                                                    computed:{
                                                            //使用对象展开运算符将getter混入computed对象中
                                                                    ...mapGetters([
                                                                                'countDoneTodos',
                                                                                            'countLength'
                                                                                                    ])
                                                                                                        }
                                                                                                        }
                                                                                                        
                                                                                                        //this.$store.getters.countLength</code></pre></li></ul><h3 id="item-1-5">3.Mutation</h3><p>Mutation即同步任务处理中心,也是更改store中的状态的唯一方法,通过stire.commit('xxxx方法','xxx参数')。每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。</p><pre><code>//Mutation方法
                                                                                                        addCount(state,payload){
                                                                                                          state.count = payload.count
                                                                                                            state.age= payload.age
                                                                                                            }
                                                                                                            
                                                                                                            
                                                                                                            //发送对应的Mutation方法
                                                                                                            this.$store.commit({
                                                                                                              type:'addCount',
                                                                                                                count:count,
                                                                                                                  age
                                                                                                                  })
                                                                                                                  
                                                                                                                  
                                                                                                                  //或通过映射来进行发送
                                                                                                                  import { mapMutaions } from 'vuex';
                                                                                                                  export default {
                                                                                                                    // ...
                                                                                                                      methods: {
                                                                                                                          ...mapMutaions([
                                                                                                                              'addCount' // 映射 this.addCount() 为 this.$store.commit('addCount')
                                                                                                                                ]),
                                                                                                                                  }
                                                                                                                                  }
                                                                                                                                  </code></pre><h3 id="item-1-6">4.Action</h3><p>处理异步操作,并且返回promise,其内可以调用Mutation,commit更新store,如果是同步操作,可以直接通过mutation修改state。</p><pre><code>//Action方法
                                                                                                                                  actions:{
                                                                                                                                    addCountAct({commit},data){
                                                                                                                                        commit('addCount',data)
                                                                                                                                          }
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          //发送对应的Action方法
                                                                                                                                          this.$store.dispath({
                                                                                                                                            type:'addCountAct',
                                                                                                                                              count:count,
                                                                                                                                                age
                                                                                                                                                })
                                                                                                                                                
                                                                                                                                                
                                                                                                                                                //或通过映射来进行发送
                                                                                                                                                import { mapActions  } from 'vuex';
                                                                                                                                                export default {
                                                                                                                                                  // ...
                                                                                                                                                    methods: {
                                                                                                                                                        ...mapActions([
                                                                                                                                                            actAdd:'addCountAct' // 映射 this.actAdd() 为 this.$store.dispath('addCountAct')
                                                                                                                                                              ]),
                                                                                                                                                                }
                                                                                                                                                                }</code></pre><h3 id="item-1-7">5.Modules</h3><p>将store进行分类,使用的时候this.$store.xxx.name <br>//xxx为modules的名称,commit一致,没有变化</p><pre><code>//子store,test
                                                                                                                                                                export default{
                                                                                                                                                                  namespaced:true,
                                                                                                                                                                    state:{
                                                                                                                                                                        message:'zxp'
                                                                                                                                                                          },
                                                                                                                                                                            mutation:{
                                                                                                                                                                                changeMessage:(state,data)=&gt;{
                                                                                                                                                                                      state.message = data
                                                                                                                                                                                          }
                                                                                                                                                                                            },
                                                                                                                                                                                              actions:{}
                                                                                                                                                                                              }</code></pre><h3 id="item-1-8">6.手写vuex</h3><p>Vuex主要包含了state、getters、actions、mutations。按照日常使用,我们需要创建一个store类,store类分成两部分,一部分是构造函数,另外一部分是commit和dispatch方法。构造函数的主要工作是赋值以及响应式的处理,首先要对拿到的参数进行解构,分为state、getters、actions、mutations。然后把state和getters设置成响应式,这里实现响应式的方法可以用vue.observable或者用object.defineProperty设置get去实现,而getters需要先进行遍历。在这之后保存一下mutations和actions。接下来就是commit和dispatch的实现,这里简单一些,直接用传入的参数配合保存下来的mutations或者actions去执行对应的函数即可,当然因为state是单一数据源,如果要考虑mutations必须是同步任务,这里也可以对mutations的参数添加限制。最后vuex是通过vue.use进行注入,那么就需要提供一个install方法,在install方法中通过mixin以及beforeCreate生命周期将store注入vue实例组件。</p><pre><code>import Vue from 'vue'
                                                                                                                                                                                              
                                                                                                                                                                                              class Store {
                                                                                                                                                                                                  constructor (options) {
                                                                                                                                                                                                          const {
                                                                                                                                                                                                                      state = {},
                                                                                                                                                                                                                                  getters = {},
                                                                                                                                                                                                                                              mutations = {},
                                                                                                                                                                                                                                                          actions = {}
                                                                                                                                                                                                                                                                  } = options
                                                                                                                                                                                                                                                                          this.state = Vue.observable(state)
                                                                                                                                                                                                                                                                                  // 此处不直接 this.getters = getters,是因为下面的代码中要方法 getters 中的 key
                                                                                                                                                                                                                                                                                          // 如果这么写的话,会导致 this.getters 和 getters 指向同一个对象
                                                                                                                                                                                                                                                                                                  // 当访问 getters 的 key 的时候,实际上就是访问 this.getters 的 key 会触发 key 属性的 getter
                                                                                                                                                                                                                                                                                                          // 会产生死递归
                                                                                                                                                                                                                                                                                                                  this.getters = Object.create(null)
                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                          Object.keys(getters).forEach(key =&gt; {
                                                                                                                                                                                                                                                                                                                                      Object.defineProperty(this.getters, key, {
                                                                                                                                                                                                                                                                                                                                                      get: () =&gt; getters[key](this.state)
                                                                                                                                                                                                                                                                                                                                                                  })
                                                                                                                                                                                                                                                                                                                                                                          })
                                                                                                                                                                                                                                                                                                                                                                                  this.mutations = mutations
                                                                                                                                                                                                                                                                                                                                                                                          this.actions = actions
                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                      commit (type, payload) {
                                                                                                                                                                                                                                                                                                                                                                                                              // 执行this.mutations里对应函数
                                                                                                                                                                                                                                                                                                                                                                                                                      this.mutations[type](payload)
                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                  dispatch (type, payload) {
                                                                                                                                                                                                                                                                                                                                                                                                                                          this.actions[type](payload)
                                                                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                  const install = (Vue) =&gt; {
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Vue.mixin({
                                                                                                                                                                                                                                                                                                                                                                                                                                                              beforeCreate() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          if (this.$options.store) { // 根组件
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          this.$store = this.$options.store
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      } else if (this.$parent &amp;&amp; this.$parent.$store) { // 子组件
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      this.$store = this.$parent.$store
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                })
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // 导出模块
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                const vuex = {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Store,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    install
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    export default vuex</code></pre><h2 id="item-2">最后</h2><p>走过路过,不要错过,点赞、收藏、评论三连~</p>