state也就是vuex里的值,也即是整個vuex的狀態,而strict和state的設置有關,如果設置strict為true,那麼不能直接修改state里的值,只能通過mutation來設置 例1: 渲染如下: 當我們在控制台修改store.state.coun里的值時頁面會自動更新,例如: 此時 ...
state也就是vuex里的值,也即是整個vuex的狀態,而strict和state的設置有關,如果設置strict為true,那麼不能直接修改state里的值,只能通過mutation來設置
例1:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="https://unpkg.com/[email protected]/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>
渲染如下:
當我們在控制台修改store.state.coun里的值時頁面會自動更新,例如:
此時頁面自動更新了,變為了:
我們設置一個strict屬性看看:例2:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="https://unpkg.com/[email protected]/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>
此時渲染如下:
當我們在控制台輸入store.state.count=2後,如下:
控制台報錯了,頁面渲染如下:
可以看到設置strict後,雖然能直接更改vuex里的值,但是會出現一條報錯信息,即嚴格模式下vuex會給出一條提示,提示我們只能通過mutation來修改。
源碼分析
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