首先声明这一篇完全是根据同事的视频学习的笔记哈~~
MVC
由于其实MVVM、MVP都是基于MVC,所以先看MVC的组成:它主要是抽象出model和view,通过双向绑定,让view可以根据model的状态进行更新
比如发生了一次view的点击,其实这个点击会先给controller,然后controller把动作给model,让model去做事情,然后view会监听model的变化。
MVC
MVC的优点:
实现视图层和业务层的分离,一定程度上降低耦合性
降低耦合性能够提高代码可维护性,增强协作的可能性
提高复用性,例如一个model对应多个view
当controller里面的view越来越多,model也会越来越多,如果一个model被多个view监听,这个view可能引发了新的model修改,然后整个数据流就会很混乱:
MVC的缺点
MVC的缺点:
没有明确模块间的依赖关系和调用方式,导致没有真正的分离
没有明确的状态同步的方式,数据流复杂
所以MVC对于复杂大型项目不容易拓展,于是延伸出了Flux架构。
Flux
它的主要特点就是单向数据流:
flux
Action其实是需要触发状态变更的一个动作,而非仅限于用户操作哦~ 一个完整的数据流是酱紫的:例如一个view点击,会发一个action携带点击相关的参数给dispatcher,dispatcher将动作给store,store去做一些操作影响状态的变更,变更的时候会发一个change事件,让view去更新界面。
下面看一个iOS上面的实现:
store的职责主要是
它的实现大概是酱紫的:
Action就是被传递的动作啦,它主要由两部分组成:类型 & 附带的数据,例如点击action可以附带一下被点击的信息之类的:
type一般就是枚举,举个例子~ 例如type是购买,payload是购买数量。
dispatcher主要是动作的分发,将动作转发给对应的store。所以他的职责主要是:
Summary - flux
实现了View -> Dispatcher -> Store -> View 的单向数据流
本身是允许多个store的,但是这样又会有多个数据源的状态同步等问题,所以推荐一个store
Action是唯一可以造成状态变化的方式,比MVC各种方式都可以触发操作要更明确
dispatcher全局唯一,对于单store的情况比较多余
Redux
Redux
store仍旧维护状态,和flux的区别就是规定整个app只有一个store,action仍旧是动作;不一样的是引入了一个处理同步数据流的reducer,以及处理异步数据流的middleware
例如,操作view的时候也会发出一个action,由于只有一个store,所以可以直接给store,然后store会把动作交给reducer,reducer根据action以及旧的state生成新的state返回给store,store中的state就会更新,也就会通知view去更新显示。
reducer就是一个纯函数,输入就是oldState以及action,然后输出就是一个newState,注意这里就类似函数式编程,reducer是不应该改动到对象的属性的,就是不应该产生副作用,仅仅是用于计算的感觉。也就是无论执行多少次,结果都一样,无论对象是什么,只要输入的一致,输出就不变。
所以reducer不可以修改传入的参数;不能执行有副作用的操作例如调用API请求(每次返回的结果可能不同);也不能调用非纯函数。
middleware是处理异步工作流的,例如点击按钮以后会请求API,区别是middleware是没有返回的:
middleware的点赞流程
redux的重要原则:
单一数据源store,避免多状态同步的问题
state是只读的(这里的理解猜测是:也就是不immutable的,reducer会返回一个新的state对象而非在原有的state上面做修改)
引入纯函数的reducer,不会带有副作用
flux 和 redux 的区别
state作为维护状态的对象的基类,没有什么属性,不同state只要继承基类即可,然后添加自己的属性:
store的主要职责为:
它的实现就酱紫:
注意哦,这里是给了store一个reducer和一个middleware,然后reducer里面可以根据处理的action的class来区分如何处理,或者让它内部维护的reducer array来处理;当然你也可以在store里面维护一个dict,记录action对应的reducer,这样就要存很多reducer而已。
action在这里会多一个属性,是不是需要middleware先handle,store会根据这个属性来决定把action给reducer还是middleware,其他两个属性类似flux:
reducer你可以定义一个协议,也可以定义基类,注意handle是一个纯函数:
middleware和reducer非常类似,只是handle action的时候没有返回值:
middleware在处理action里面可以先做异步动作,然后当异步过程结束以后,再调用store的dispatch action,传入新的action,由于这里可能会用到store,所以其实middleware和reducer是可以持有store哒~ 如果使用注意不要循环引用即可
举个例子,比如点击动态的点赞,按钮会变成选中状态,并且点赞数+1:
创建store,调用点赞的middleware以及reducer的handle action
action需要定义一个type,这里就是点赞type,并携带一个其他数据属性也就是动态的model
store分发action给middleware,middleware会根据action type进行不同处理,这里会先取动态的model去远端请求点赞api
middleware的请求回来以后会把action的设为NO以后传递给store,store再去分发这个action给reducer
reducer收到action以后也是通过type找到处理方式,然后修改state里面的属性(),返回新的state(这里没有创建新的对象,但严格意义应该创建新的)
store会设置新的state,触发observers的state change监听,view在这里把点赞按钮设为选中。
什么时候用redux
需要单一数据源
状态较多
视图层级or数目多
Discussion
Finally,用个人角度以及和同事聊天的感受来探讨一下这几种模式叭,MVX系列(MVC / MVP / MVVM)和Flux其实都只是形式或者说实现上面的不一样,如果MVC会造成绑定混乱,例如按理说,无论是VC绑定还是VM和V绑定,其实都应该是一对一,但是经常我们不能保证这一点,毕竟项目很庞大。
Flux 和 Redux 很重点的一个事儿是:对状态进行梳理。也就是尽量减少那种 VM 一对多的关系所造成的的连锁反应。并且,它更容易测试以及理解的一点在于,监听状态改变后做相应的操作,这一点相比MVX系列更清晰。但是本质上,还是可能会造成连锁反应,只是它更强调有限的状态,让系统更可控的感觉。
所以归根结底,好的设计模式其实不仅仅是说实现上,更重要的是我们如何避免耦合,或者说让耦合能做到泾渭分明。这个是根本,如果可以做到其实用 MVX 和 flux 区别不会特别大,但是 flux 仍旧是一个很好的模式,因为它很清晰有条理,强迫我们去梳理出一个个独立的状态形成单向数据流,尽量减少不可控的连锁反应。
领取专属 10元无门槛券
私享最新 技术干货