原文链接:https://segmentfault.com/q/1010000012841623
简单来说,就是从客户的角度来看,直接修改state是没有问题的,功能照样可以实现,但是!!!从开发者多角度看很不友好,我们使用commit来提交mutation修改数据是希望可以记录下每一次修改的状态,出现问题时就可以很快的知道是哪里出错,还有!!!在严格模式下不能直接修改state,会报错。
之前阅读官方文档时,了解到当要改变vuex的state的时候必须要用commit来提交一个mutation,像这样:
this.$store.commit("someState",...) //或者 this.$store.dispatch("changeSomeState",...)
但是一个刚接触vue的朋友在写代码的时直接使用赋值的形式来改变state,像这样
this.$store.state[someState] = XXX
也能够成功完成他想要的效果,
那么请问,
这里的官方文档中说的必须要使用commit提交一个Mutation来改变state,是仅仅需要一个规范来代码可读性或者说明确每个状态改变的地方,还是说有其他的作用,直接赋值会有什么弊端吗?
从效果上来说没有影响但是不建议这么做.谈一下我的理解.
vuex 从功能上来说就是一个前端缓存系统.
解决了 SPA 不同组件之间数据共享的问题
那么到底如何用,为什么会存在 mutation 等概念呢?
你可以看一下官方文档示例 shopping-cart.
这个范例模拟电商中,添加商品到购物车,并进行结算的逻辑.
核心逻辑包括.
- 拉取产品列表并显示
- 点击添加到购物车
- 进行结算.
站在用户的角度,用户只做了两件事
- 将商品添加到购物车
- 结算
在这里,添加商品会修改购物车的显示.
最简单的做法就把这些数据都放在父组件.
但是看一下官方示例如何实现的.
定义了两个组件
- ProductList.vue 用来加载商品列表
- ShoppingCart.vue 处理结算的问题
那么组件数据呢?全部放在了 vuex 中进行管理.
为什么要这么做,为什么不直接放在父组件里面呢?
- 更清晰的代码结构,每个组件都有自己的职责,不必为了实现不同组件之间的交互而定义额外的数据总线或产生一个数据庞大的父组件来作为周转
- 可复用的逻辑,将常用的业务利用 vuex 拆分成基于状态而非过程控制的代码.
- ...
在回到问题本身直接修改有什么危害?
从功能上说没有危害,但是从代码构建角度是没有理解 vuex 这个神器怎么用!!!
不要只把 vuex 当做一种全局修改数据的工具.它的意义在于
把跨组件的交互拆分为基于状态管理的处理模式,是更高层的逻辑抽象
针对此提一下一些使用技巧.
下回在用 vuex 时考虑如下问题:
1.对于用户层暴露的逻辑事件是什么?
看购物车可已看出就两个事件,添加商品,和结算
2.这个事件会影响那些数据
然后把状态图画出来,利用 vuex 中的语法编写.
回到上面问题,假设现在用户的购物车添加了收藏,取消等逻辑,此时对于你而言只是单纯的增加了 mutations 和相关事件的状态处理.数据结构并没有变化,这就是好的设计
使用如vuex,redux本身就是希望基于这样一个数据结构的约定,使得项目代码更加直观和简单
所谓直观和简单是说:
每一个状态树对应整个项目的一个状态,而每次Mutation则代表了一次项目状态的改变,为了能够更加直观地观察到这样的变化(使得我们能够迅速追踪或者说发现项目状态的变化),我们使用flux这样的框架思想去约定变化,使我们看代码时一眼就能看出,这是一次状态树的变化
更贴合实际的一个例子就是
当我们的项目出现bug时,要追踪某一时刻查看在哪个过程中state的某个值出现了问题,我们可以直接去约定的mutation-type表中去找每次状态的变化,变了什么或者说是怎么变的,方便更快速地定位问题和分析问题。
如果不想使用这样的约定,就不要用vuex,redux之类,直接在根入口自定义一个全局空间,其他子模块统一访问全局空间就行了。
就使用vue-devtools来说,直接给state赋值,在浏览器控制台上不会显示修改记录。而通过commit来修改state,会在浏览器控制台上清楚的看到每一个state属性修改的详细的记录。
如果在某个state属性没有同步到页面上,不知道是自己程序逻辑还是vuex赋值出了问题。就直观使用来说,使用commit的方法能更方便程序的调试。