zoukankan      html  css  js  c++  java
  • vuex源码分析(二) state及strict属性 详解

    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

  • 相关阅读:
    java 多线程2
    java 多线程1
    java Object
    java 模板
    03015_JSTL技术
    运维人员常用的Linux命令总结
    oracle的userenv和nls_lang详解
    Oracle字符集检查和修改
    sql语句中(+)的作用
    Oracle事务Transaction
  • 原文地址:https://www.cnblogs.com/greatdesert/p/11423783.html
Copyright © 2011-2022 走看看