vuex源码:state及strict属性

更新日期: 2019-08-09阅读: 2k标签: 源码

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>

渲染如下:

count:1

当我们在控制台修改store.state.coun里的值时页面会自动更新,例如:

store.state.count=2
//2

此时页面自动更新了,变为了:

count:2

我们设置一个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>

此时渲染如下:

count:1

当我们在控制台输入store.state.count=2后,如下:


控制台报错了,页面渲染如下:

count:2

可以看到设置strict后,虽然能直接更改vuex里的值,但是会出现一条报错信息,即严格模式下vuex会给出一条提示,提示我们只能通过mutation来修改。

 

源码分析

我们直接修改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


链接: https://www.fly63.com/article/detial/5214

Js中的 forEach 源码

在日常 Coding 中,码农们肯定少不了对数组的操作,其中很常用的一个操作就是对数组进行遍历,查看数组中的元素,然后一顿操作猛如虎。今天暂且简单地说说在 JavaScript 中 forEach。

微信小程序代码源码案例大全

克隆项目代码到本地(git应该都要会哈,现在源码几乎都会放github上,会git才方便,不会的可以自学一下哦,不会的也没关系,gitHub上也提供直接下载的链接);打开微信开发者工具;

Node 集群源码初探

随着这些模块逐渐完善, Nodejs 在服务端的使用场景也越来越丰富,如果你仅仅是因为JS 这个后缀而注意到它的话, 那么我希望你能暂停脚步,好好了解一下这门年轻的语言,相信它会给你带来惊喜

Vue源码之实例方法

在 Vue 内部,有一段这样的代码:上面5个函数的作用是在Vue的原型上面挂载方法。initMixin 函数;可以看到在 initMixin 方法中,实现了一系列的初始化操作,包括生命周期流程以及响应式系统流程的启动

vue源码解析:nextTick

nextTick的使用:vue中dom的更像并不是实时的,当数据改变后,vue会把渲染watcher添加到异步队列,异步执行,同步代码执行完成后再统一修改dom,我们看下面的代码。

React源码解析之ReactDOM.render()

React更新的方式有三种:(1)ReactDOM.render() || hydrate(ReactDOMServer渲染)(2)setState(3)forceUpdate;接下来,我们就来看下ReactDOM.render()源码

React源码解析之ExpirationTime

在React中,为防止某个update因为优先级的原因一直被打断而未能执行。React会设置一个ExpirationTime,当时间到了ExpirationTime的时候,如果某个update还未执行的话,React将会强制执行该update,这就是ExpirationTime的作用。

扒开V8引擎的源码,我找到了你们想要的前端算法

算法对于前端工程师来说总有一层神秘色彩,这篇文章通过解读V8源码,带你探索 Array.prototype.sort 函数下的算法实现。来,先把你用过的和听说过的排序算法都列出来:

jQuery源码之extend的实现

extend是jQuery中一个比较核心的代码,如果有查看jQuery的源码的话,就会发现jQuery在多处调用了extend方法。作用:对任意对象进行扩;’扩展某个实例对象

webpack 源码从零开始:apable模型

最近在看webpack的源码,发现有个比较头疼的点是:代码看起来非常跳跃,往往看不到几行就插入一段新内容,为了理解又不得不先学习相关的前置知识。层层嵌套之后,发现最基础的还是tapable模型,因此先对这部分的内容做一个介绍。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!