前言
本篇博客主要回顾了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)=>{ 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 => { 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</code></pre><h2 id="item-2">最后</h2><p>走过路过,不要错过,点赞、收藏、评论三连~</p>