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/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>
渲染如下:

当我们在控制台修改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/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>
此时渲染如下:

当我们在控制台输入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