Open z2014 opened 7 years ago
你好,关于第一个问题:vuex中修改state必须通过commit提交mutation,而不是通过直接修改state。有两个地方没太明白:
1.在commit提交mutation时,会使用_withCommit这个函数,但是其中this._committing = true目的是啥?哪里watch了这个参数是否为true?
2.你在上面提到一句话:......所以我们往往是做了一层深拷贝之后,才在组件中对数据进行修改。.......在commit提交mutation这种方式的时候,哪里进行了深拷贝?难道说commit函数的返回值是一个新的state ?
这些,我在源码中都没有看到,或许是我功力尚浅,请教一下。
@BigKongfuPanda 你好,关于第一个问题,你可以把它理解成一个开关,通过commit提交,会将this._committing修改为true,而如果不通过commit提交,则他还会是false,则无法修改。 关于第二个问题,是我之前在做业务时,将state中的数据拿来直接排序,这样会报错,我们需要暴力深拷贝处理之后,再进行组件级的操作
谢谢回答。但是第一个问题,依然还是存在疑问。_withCommit函数的代码中:
_withCommit (fn) { const committing = this._committing; this._committing = true; fn(); this._committing = committing; }
就算是this._committing == false,下面的回调函数fn依然也会执行啊,这个fn就是修改state的函数吧。
从vuex/store.js中的commit方法里面这段代码可以看得出来:
this._withCommit(() => { entry.forEach(function commitIterator (handler) { handler(payload) }) })
所以,我的意思是,直接修改state,即使不经过_withCommit函数来修改state,此时this._committing == false,那么vuex中有没有对这种情况进行处理呢?
@BigKongfuPanda 刚刚在工作。_withCommit这个函数只有在你用commit提交的时候才会调用啊,如果你在外部去修改state,就不会修改this._committing = true,那么在mutation的回调函数中就会报错
哦。我上面有点说错了。我晓得_withCommit这个函数只有在用commit提交的时候才会调用的。
当外部去修改state,是会报错,但是这个报错的逻辑代码在哪儿呢? 我来回看了几次,都没有找到,您说在mutation的回调函数里面,能够帮我指明不?谢谢。
我试了下不通过commit提交mutation,直接修改state,控制台并没有报错,而且数据一样是响应式的。
'use strict'试试
刚试了下严格模式下,会报错。
demo 有吗,我看看
第一次,严格模式设置错了。
我知道了。限制在mutation中去修改state,是为了便于将所有的状态变更都能够被vue的调试工具跟踪到。 我分别试了下两种方式,确实是commit提交mutation的时候,state的变化会被记录下来。
大美女开始写博客了
@wkk123 认错人了
昨天听完同学来我们团队做的分享之后,自己又去看了一遍源码,结合自己之前项目的一些理解,写一篇博客,这里是原文链接.
在看源码前,结合之前的自己的项目实践,有以下几个问题:
接下来针对上面的问题,结合源码做一下解答:
我们在一个项目中引入vuex是下面的这样一个注入:
其实从上面的这段代码就不难看出,store应该是一个构造函数,对应着vuex源码中store.js 在store.js中有这样的一段代码,简化如下:
这段代码就很好的解释了第一个问题,当我们通过dispatch一个action之后,数据到达mutation里面,我们会将此时的是否编辑状态更改为true,然而当我们直接在组件中修改的时候,此时的_commiting状态依然为false,所以我们往往是做了一层深拷贝之后,才在组件中对数据进行修改。
接下来是第二个问题,为什么要设置一个getter呢? 在我原先的项目中,我的getters里面基本都是这样的函数
其实就是把state中的状态在原封不动的映射出去,当时我在想为什么需要这层映射,直接把state映射出去不好吗,对于一个module里面,如果state里面数据很多的话,那getters也要写很多,岂不是很烦?
但其实看完源码后发现这层getters是必不可少的,为什么呢?
这首先得追溯到vue是如何实现双向绑定的这个问题上,如果不了解的话,可以去看看我的这一篇博客,vue框架本身在你获取一个数据的时候,比如obj.aa,也就是在这个对象的getter里面,就会把你放进一个通知队列里面,当这个对象被重新setter后,会遍历通知队列告诉你我更新了,你也要更新了,并且如果这个数据有watch的话,同时会执行watch的回调函数。
那一个问题就是vuex中的数据是如何实现双向绑定的呢?是和vue一样的方式吗?vuex的源码非常简洁,里面并没有做和vue同样的事情,其实他正是通过了getter方法,与vue的watch相挂钩,才实现了vuex的双向绑定,来看源码中的如下代码
对于一开始的困惑也就解答完了,那一开始说的新大陆是什么呢?
在项目中,当我们对页面上的数据做一些删除或者更新的操作时,我往往会在更新结束之后,在dispatch一个查询操作,就是这个dispatch其实他是可以接收多个action的,而且向每个action传递的参数也一样(主要是之前也没这么用过,读源码的时候发现还能有这种操作,源码如下:
这篇文章的思路讲的还是比较跳的,没有对源码整体文件目录上做分析就直接讲代码,如果没太看懂的话可以先去看开头的那篇分析,很详细。 最后,欢迎批评指正~