Vuex 的核心概念及底层原理

核心概念

1.State --- this.$store.state.xxx 取值;

2.Getter --- this.$store.getters.xxx 取值(类似于计算属性,还是获取的Vue的数据缓存,用来取值的);

3.Mutation --- this.$store.commit('funcName') 赋值;

4.Action --- this.$store.dispatch('funcName') 通知携带上下文,还是交给commit通知mutation赋值;

5.Module --- 模块化,对我们的状态进一步的做一些组织管理。

底层原理


1.State --- 提供响应式数据;

2.Getter --- 借助Vue的计算属性 computed 来实现缓存;

3.Mutation --- 更改state的方法;

4.Action --- 触发mutation的方法,一般异步;

5.Module --- 大的状态树,通过Vue.set 动态添加state到响应数据中。

根据描述,我们模拟了一个简易的vuex核心函数:


import Vue from 'vue'
const Store = function Store(options = {}) {
    const {state = {}, mutations={}} = options;
    this._vm = new Vue({
        data: {
            $$state: state
        },
    });
    this._mutations = mutations;
}
Store.prototype.commit = function(type, payload) {
    if(this._mutations[type]) {
        this._mutations[type](this.state, payload)
    }
};
Object.defineProperties(Store.prototype, {    //修改属性的默认特性,必须使用ECMAScript5提供的Object.defineProperty()方法。
    //而该方法接收三个参数:属性所在的对象,属性名字,和一个描述符对象;
    //描述符对象:configurable,emumerable,writable,value 。设置其中一或多个的值,就可以修改对应的特性值。
    state: {
        get: function() {
            return this._vm._data.$$state
        }
    }
});
export default {Store};

我们的main.js代码如下:

import Vue from 'vue'
import Vuex from './min-vuex.js'//根据老师,实现的简易vuex原理的commit方法
import App from './App.vue'

Vue.use(Vuex)
Vue.config.productionTip = false

const store = new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {    
        increment(state) {
            state.count++
        }
    },
})

Vue.prototype.$store = store;
new Vue({
    // store,
  render: h => h(App),
}).$mount('#app')

我们的app.vue代码如下:

<template>
  <div id="app">
    {{ myGetCount }}
        <br>
        <!-- {{ $store.getters.doubleCount }} -->
        <br>
        <!-- <button @click="$store.dispatch('incrementAction')">Action-count++</button> -->
  </div>
</template>

<script>
export default {
  name: 'App',
    computed: {
        myGetCount() {
            return this.$store.state.count
        },
    },
}
</script>


测试可正常实现commit方法: