vuex源碼分析(二) state及strict屬性 詳解

state也就是vuex裏的值,也便是整個vuex的狀態,而strict和state的設置有關,若是設置strict爲true,那麼不能直接修改state裏的值,只能經過mutation來設置html

例1:vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
</head>
<body>
    <div id="app">
        <p>count:{{count}}</p>
    </div>
    <script> const store = new Vuex.Store({ state:{count:1} }) var app = new Vue({ el:"#app", store, computed:{ count(){return store.state.count } } }) </script>
</body>
</html>

渲染以下:vuex

當咱們在控制檯修改store.state.coun裏的值時頁面會自動更新,例如:npm

此時頁面自動更新了,變爲了:數組

咱們設置一個strict屬性看看:例2:app

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
</head>
<body>
    <div id="app">
        <p>count:{{count}}</p>
    </div>
    <script> const store = new Vuex.Store({ state:{count:1}, strict:true                             //新增一個strict屬性,值爲true
 }) var app = new Vue({ el:"#app", store, computed:{ count(){return store.state.count } } }) </script>
</body>
</html>

此時渲染以下:ide

當咱們在控制檯輸入store.state.count=2後,以下:函數

控制檯報錯了,頁面渲染以下:源碼分析

能夠看到設置strict後,雖然能直接更改vuex裏的值,可是會出現一條報錯信息,即嚴格模式下vuex會給出一條提示,提示咱們只能經過mutation來修改。this

 

源碼分析


writer by:大沙漠 QQ:22969969

咱們直接修改state會觸發更新以及strict嚴格模式的控制都是在vuex內部resetStoreVM整個函數內實現的,以下:

function resetStoreVM (store, state, hot) {       //從新存儲數據
    var oldVm = store._vm; // bind store public getters
    store.getters = {};                                         //給store定義一個getters屬性,值爲一個對象
    var wrappedGetters = store._wrappedGetters;                 //獲取store的全部getter數組信息
    var computed = {}; forEachValue(wrappedGetters, function (fn, key) {           //遍歷wrappedGetters
      // use computed to leverage its lazy-caching mechanism
      computed[key] = function () { return fn(store); };          //將getter保存到computed裏面
      Object.defineProperty(store.getters, key, {                 //設置store.getters的key的訪問器屬性
        get: function () { return store._vm[key]; }, enumerable: true // for local getters
 }); }); // use a Vue instance to store the state tree
    // suppress warnings just in case the user has added
    // some funky global mixins
    var silent = Vue.config.silent;                             //保存Vue.config.silent的配置
    Vue.config.silent = true;                                   //設置Vue.config.silent配置屬性爲true(先關閉警告)
    store._vm = new Vue({                                       //建立new Vue()實例把$$state和computed變成響應式的
 data: { $$state: state }, computed: computed }); Vue.config.silent = silent;                                 //將Vue.config.silent復原回去

    // enable strict mode for new vm
    if (store.strict) {                                         //初始化Strore時,若是給strict傳入了true
      enableStrictMode(store);                                    //則調用enableStrictMode()函數
 } if (oldVm) { if (hot) { // dispatch changes in all subscribed watchers
        // to force getter re-evaluation for hot reloading.
        store._withCommit(function () { oldVm._data.$$state = null; }); } Vue.nextTick(function () { return oldVm.$destroy(); }); } }

從上面看到vuex內部建立一個vue對象並把state設置爲了data對象裏,所以有響應式的功能,而若是傳入了strict,則調用enableStrictMode函數,該函數實現以下:

function enableStrictMode (store) {       //嚴格模式下,觀察this._data.$$state的變化
    store._vm.$watch(function () { return this._data.$$state }, function () {   //若是this._data.$$state發生變化時,store._committing不爲true,則報錯(不是經過vuex的接口來修改時)
 { assert(store._committing, "do not mutate vuex store state outside mutation handlers."); } }, { deep: true, sync: true }); }

也就是調用vue.$watch去觀察 this._data.$$state的變化,也就是vuex裏的state的變化,若是有變化且store._committing不爲true則報錯

store._committing是vuex裏的一個屬性,若是是經過mutation修改state時就會設置store._committing爲true,不然store._committing爲false

相關文章
相關標籤/搜索