头图

前言

本篇博客主要回顾了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
  • 组件内

    export default {
        computed:{
            //使用对象展开运算符将getter混入computed对象中
            ...mapGetters([
                'countDoneTodos',
                'countLength'
            ])
        }
    }
    
    //this.$store.getters.countLength

3.Mutation

Mutation即同步任务处理中心,也是更改store中的状态的唯一方法,通过stire.commit('xxxx方法','xxx参数')。每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。

//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')
  ]),
  }
}

4.Action

处理异步操作,并且返回promise,其内可以调用Mutation,commit更新store,如果是同步操作,可以直接通过mutation修改state。

//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')
  ]),
  }
}

5.Modules

将store进行分类,使用的时候this.$store.xxx.name
//xxx为modules的名称,commit一致,没有变化

//子store,test
export default{
  namespaced:true,
  state:{
    message:'zxp'
  },
  mutation:{
    changeMessage:(state,data)=>{
      state.message = data
    }
  },
  actions:{}
}

6.手写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实例组件。

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 => {
            Object.defineProperty(this.getters, key, {
                get: () => 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) => {
    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) { // 根组件
                this.$store = this.$options.store
            } else if (this.$parent && this.$parent.$store) { // 子组件
                this.$store = this.$parent.$store
            }
        }
      })
}


// 导出模块
const vuex = {
  Store,
  install
}

export default vuex

最后

走过路过,不要错过,点赞、收藏、评论三连~


驰骥
1 声望0 粉丝

认真、学习、思考、执行、耐心、主动