Vuex的源码阅读与分析

43次阅读

共计 2331 个字符,预计需要花费 6 分钟才能阅读完成。

一、Vuex 是如何注入到 Vue 中的

beforeCreate 执行时将 $store 挂载到 vue 的原型链上。

let Vue;

function install(vm,storeName='$store'){
    Vue = vm;
    Vue.mixin({beforeCreate() {if(this.$options.store){
                // 将 $store 挂载到 Vue 的原型上
                Vue.prototype[storeName] = this.$options.store;
            }
        }
    })
}

二、Vuex 如何实现状态响应式核心

本质上是采用了 Vue 的数据响应原理

// 注册 state
const store = new vuex.Store({
    state:{inputText:''},
    ......
});
//new vuex.Store 的时候将 state 映射到 Vue 实例中的 data 上
class Store{constructor(options={}){
        this.state = new Vue({data:options.state})
    }
    .....
}

三、getter

getter 的作用是对 state 进行计算处理,类似 vue 的 computed 对属性进行计算一样。getter 的原理是利用 Object.defineProperty 劫持属性的 getter 将计算后的结果保存在 vuex 的 getter 中。

registerGetter(getters){this.getters = {}
    let vm = this.state;
    for (const key in getters) {if (getters.hasOwnProperty(key)) {
            Object.defineProperty(this.getters,key,{get(){
                    // 调用 vuex 参数中 getter 的函数,并将结果缓存在 getter 里面
                    return getters[key](vm);
                }
            })
        }
    }
}

四、Mutations 如何更新状态

1、注册 mutations 函数

const store = new vuex.Store({
    state:{inputText:''},
    mutations:{
        /** 这里的 state 实际上是一个 vue 的实例 */
        updateInputText(state,payload){state.inputText = payload;}
    }
});

2、更改状态必须触发 commit 函数,commit 函数调用 mutaions 里面的函数,并将 vue 实例和需要更改的数据传递给 mutations 函数。

commit(m_name,payload){const fn = this.mutations[m_name];
    fn(this.state,payload);
}

3、为什么 mutations 必须是异步的?

 如果是异步的会导致 devtool 调试困难,很难追踪到状态的改变。

五、action

1、action 类似 mutation,不同的在于:action 提交的是 mutation;action 可以是异步,但 mutation 只能是同步。
2、注册 actions

const store = new vuex.Store({
    state:{inputText:''},
    mutations:{updateInputText(state,payload){state.inputText = payload;}
    },
    actions:{text({commit}){
            // 模拟一个异步操作
            setTimeout(() => {commit('updateInputText')
            }, 1000);
        }
    }
});

3、分发 action,必须触发 dispatch 方法。dispatch 函数会将 commit/state/getters 传递给 action 函数。

dispatch(a_name,arg){
    // 源码在此处使用 promise 进行异步处理
    const fn = this.actions[a_name];
    fn({
        commit:this.commit,
        state:this.state,
        getters:this.getters
    },arg);
}

4、为什么需要 action 进行异步管理?
场景:假如有两个异步操作 A 和 B,它们都会操作同一个 mutation,并且 B 需要在 A 提交 mutation 后才提交。
当有这样复杂的操作时就需要使用 action 来处理异步问题了。

actions: {
  // ...
  actionB ({dispatch, commit}) {return dispatch('actionA').then(() => {commit('someOtherMutation')
    })
  }
}

六、常用的插件

1、vuex-persistedstate 使用浏览器的本地存储(local storage)对状态(state)进行持久化。这意味着刷新页面或关闭标签页都不会删除你的数据。
2、vuex-shared-mutations 可在不同的标签页之间同步状态。它通过 mutation 将状态储存到本地存储来实现。选项卡、窗口中的内容更新时触发储存事件,重新调用 mutation,从而保持状态同步。
3、vuex-i18n 允许你轻松地用多种语言存储内容。让你的应用切换语言时更容易。
4、vuex-loading 有助于你管理应用中的多个加载状态。这个插件适用于状态变化频繁且复杂的实时应用程序。
5、vuex-cache 可以缓存 Vuex 的 action。例如,如果你从服务器检索数据,这个插件将在第一次调用该 action 时缓存结果,然后在之后的 dispatch 中,直接返回缓存的值。必要时清除缓存也很简单。

参考文章

https://www.cnblogs.com/haishen/p/11315669.html

正文完
 0