相信不少用过react和vue等框架的人都有思考过这个问题。React的出现,随之带来了flux这一设计理念。从React的Reflux、Redux,再到vue的vuex,一路使用过来,我以为是该总结一下的时候了。html
flux的机制已经有太多文章写过了,这里就再也不多说。若是还不了解的,能够参看阮一峰的Flux 架构入门教程。这里简单介绍一下目前主流的三种flux架构:前端
Reflux是我最先接触的flux架构,它把flux的结构简化了,带来了一些便利,但却作得不够好。它的store并不惟一,而且容许你创建多个store。若是处理很差,维护起来也是够呛。vue
Redux在这方面就作得很棒,它的store只有一个,而且引入了immutable的概念,使得store的可预测性更进一步。可是它的异步操做是痛点,虽然有如saga这种优秀的中间件,但对于新手来讲,仍是很容易绕晕。react
vuex这方面作得挺不错,它把异步操做限定在了actions阶段,减小了不少繁琐步骤。它的store也是惟一,但你能够在任何地方用this.$store去引用,方便的同时,对习惯很差的同窗,也会带来一些隐患。ajax
好了,接下来咱们该进入主题了。vuex
前两天,和同事在store里面应该存放何种数据的问题上产生了分歧,因而我查了很多资料,也跟一些技术大牛进行过探讨。总结起来,目前主流的观点有两种:数据库
store只存放公共数据,组件的数据、状态自行维护小程序
全部数据都应走store,view层只管展示数据,这也是flux官方所推荐的作法后端
这里特别强调一下,本文所探讨的是SPA应用。因此,如无特殊说明,这里指的组件,特指页面级组件,或者说路由级组件,并不是单组件。另外,flux官方并没有数据的概念,全部数据均是状态。那我为何要特地抽出来呢?后面会说。微信小程序
持观点1的人认为:只有公共的数据、须要跨组件的数据才应放入store。优势是store小,页面组件内的数据没必要绕来绕去,开发简单。
持观点2的人认为:呃,貌似我本身也差很少这种思想,为免带入我的思想,这里就不妄自猜度他人想法了。
目前各方都有必定的支持人数,那么,要理清这个问题,咱们就得先把store的角色定位好。是作为数据中心呢?仍是作为全局变量仓库?或者还有另外的想法?
自从接触flux以来,我也一直遵循第二种思路,但又不彻底是。store是什么?从字面上理解,就是一份存储,一份放在本地的存储。再来看一下咱们目前的先后端交互,拉取 => 展示,再拉取 => 再展示。每切换一次页面,都要再拉取一次数据。咱们为何不能作到更好呢?把store定位为一份服务器数据本地快照如何?没错,这就是个人思路。
传统应用开发,咱们的应用程序都是直接和数据库交互的。但前端不行,抛开还须要后端程序提供接口不说,前端与数据库中间还隔着http这层,这就产生了巨大的延时。因此,为何咱们不能在本地创建一份数据快照?用store来作这事是否是合适?
也许你会说,localStorage、indexDB来作这事才更合适。localStorage大小且不说,你还须要借助JSON来进行数据维护。而indexDB,操做起来也并不简便。而且,他们的存取速度与store也明显不是一个级别(虽然用户几乎感受不到差别)。
除相似autocomplate这类的sideways数据,全部从后端拉取的数据,以页面级组件为单位,都存入store,作为服务器数据本地快照。这样,当用户切换页面时,只有view会被销毁。每次用户进入该页面,首先会拿到一份快照数据,store同时向服务器查询最新数据。若有更新,可作提示有新数据(如新浪微博)。
而对于状态(对,前面说了我把数据和状态分别开来对待。数据指业务数据,而状态,我理解为行为状态),除非是全局状态,不然,管你是页面级组件仍是单组件,自个儿内部维护。
特别说明,store里的数据,应当尽可能保持是原始的服务器数据快照,而不该该去作任何mutate,相似Redux的immutable思想。而对于add、del之类操做的结果,也不该当放入store,而只是一种状态反馈,应当在组件内部消化。
这样,咱们的store里就只有纯粹的两种东西:全局状态和业务数据(服务器数据快照)。
更进一步,咱们还能够借助本地存储把store作为本地缓存,达到重启app可当即恢复现场的效果。
用户体验,对于切换频率高的页面,用户体验直线上升。设想一下,若是数据放到页面组件内部,离开当前页数据即被销毁,当用户一秒后再次返回该页。。。
资源优化,减小对服务器的请求,对于更新周期长的数据,例如用户我的信息,彻底能够仅请求一次
可预测性,flux所提倡的数据可预测成为可能,各类数据追踪工具得以大展身手(微信小程序开发工具的数据追踪就挺不错)
可读性,component只有view逻辑,不掺杂modal逻辑,业务逻辑清晰易维护
扩展性强,例如须要加入权限控制,进行数据过滤,在store层面就能够轻松解决。而若是业务数据在组件内部。。。
统一性,全部业务数据统一存取,管理方便。
再来看看持观点1的人所反对的:
store庞大,持观点1的人首先反对的就是这个。可是,对于SPA来讲,对于现代PC来讲,你的SPA的store能达到以G为单位不?
编写繁琐,嗯,这算一个理由吧。不过,对于其所带来的优势来讲,这点牺牲并不算什么吧?
数据时效,有人提到,一次性数据(好比订单结算)不该被放入store。没错,这点咱们能够在页面destory时手动清理不是么?
单store文件难维护,有人提到,全部业务数据操做都在store里,难维护。其实利用如今的构建工具,咱们已经能够作到把各个页面组件的store单独切出来,构建时再合并,这并不会影响可维护性。
数据污染,有人担忧,这么多数据放到store里,会不会形成污染。对于这点,不管Redux和vuex,都是支持子store的。也就是命名空间的概念。好比 store.pageModule一、store.pageModule2。再配合一些测试工具(如mocha)作重名检测,这方面彻底不是问题
实际开发过程当中,还有一个常常遇到的,常常被人问起的问题:公共页面组件容易加载到非自身数据。好比文章详情页,若是先浏览了文章1,再浏览文章2,有可能先显示文章1的内容,会很怪异。其实这也是一个很容易解决的问题,进入一个页面组件时,首先加载的实际上是initialState,紧接着,flux才把store里的数据推过来。这个时候,你应该作文章id校验,只有是自身数据,才assign。
记得有人说过这样的话:“若是你不知道该不应用flux,那说明你并不须要它。” Redux的做者 Dan Abramov 说:“Flux 架构就像眼镜:您自会知道何时须要它。” 若是你的业务只是须要一个全局变量仓库,flux会不会太重?而对于大多数SPA场景,我想这个思路都是行得通的。另外,对于一次性数据比较多的应用,那这种思路或许也不太适合。
我以为最理想的状态,flux架构还能够更进一步,把store作得更纯粹一些,能够自行维护数据。具体作法是,ajax放到store层面,当请求的数据不存在或过旧时,自动拉取,而不须要经过actions来处理拉取数据的逻辑。