2

一、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


前端茅台
14 声望0 粉丝

喜欢茅台的前端开发