前端技术(一):从MV*到Flux

最近开始接触react框架,然后学习了关于react周边的一系列技术。

react全家桶包括了

react,组件化的框架,看官方文档即可

react-router,路由管理

redux, 是一个状态容器,提供可预测化的状态管理

redux-saga,数据获取等异步时间和访问缓存

react-redux,redux的官方绑定

react-router-redux ,上面三者的结合体

,immutable, 创建不可变的数据

reselect,选择器

antd ui框架  开箱即用的ui框架

Create raect-app  官方脚手架(集成react+react-dom+react-router)

Antd pro antd提供的脚手架

项目基于蚂蚁金服的dva框架,实际上是对几个流行的开源框架的整合,技术栈包括:

  • react

  • react-router

  • redux

  • redux-saga

  • dva

  • antd

有时候dva会结合umi使用:

Umi react应用开发框架,对下面等技术进行了封装,主要负责路由 

{

  preact

Webpack

React-router

Babel

Jest

}

 

负责数据,DVA不添加新的语法,只是封装了,不使用dva前,reducer, saga, action 都是分离的(分文件)

Dva  数据流前端框架,封装了redux,redux-saga,react-router

{

    redux

   redux-saga

   react-route

   等

}

 

//负责组件开发,蚂蚁金服提供的组件,用就是啦

antd

前后端分离的重要一角,现在很多工具可以快速生成这样的模拟数据了,比如easymock

//负责搭建假数据

mock

发现前端真的是深不见底啊,越学越多,周边的技术,让你眼花缭乱。这些只是冰山一角,基于框架开发,慢慢对底层的东西会遗忘,底层的东西还是非常重要滴。

在开始介绍之前,先说一说MV*。大家一定都听说过MVC,在这之后又衍生出了MVP和MVVM,这些都可以统称为MV*。但是,随着前端代码复杂度的增加,人们发现越来越难以管理程序的状态,模块之间耦合严重,代码难以调试,因此很多人认为“前端MVC已死”。

2014年,facebook提出了一个新的概念:Flux,旨在解决这些问题,其核心思想是“组件化 + 单向数据流”。这个框架很快流行了起来,并且逐渐成为目前的主流前端框架之一。为了更深刻地理解这一变化,我们来逐一比较一下它们之间的异同:

1.MVC

 

用户首先通过View发起交互,View调用Controller执行业务逻辑,Controller修改Model,然后View通过观察者模式检测到Model的变化(具体表现形式可以是Pub/Sub或者是触发Events),刷新界面显示。

从这里可以看出,主要业务逻辑都在Controller中,Controller会变得很重。MVC比较明显的缺点:

  • View依赖特定的Model,无法组件化

  • View和Controller紧耦合,如果脱离Controller,View难以独立应用(功能太少)

2.MVP

为了克服MVC的上述缺点,MVP应运而生。在MVP中,View和Model是没有直接联系的,所有操作都必须通过Presenter进行中转。View向Presenter发起调用请求,Presenter修改Model,Model修改完成后通知Presenter,Presenter再调用View的相关接口刷新界面。这样,View就不需要监听具体Model的变化了,只需要提供接口给Presenter调用就可以了。MVP具有以下优点:

  • View可以组件化,不需要了解业务逻辑,只需提供接口给Presenter

  • 便于测试:只需要给Presenter mock一个View,实现View的接口即可

3.MVVM

为了进一步解放生产力,把Presenter中调用View的接口同步数据变化的重复工作抽象出来,做成一个binder模块,这就变成了MVVM。开发者只需要指明绑定关系,binder模块会自动完成数据同步,这就是所谓的“双向数据流”,不管哪一端的数据发生变化,都会立即同步到另一端。实际上,Vue.js、Angular这些流行的前端框架都使用了双向数据流设计。

双向数据流极大地简化了开发者的工作,但是诟病也随之而来。由于绑定的随意性,某个View对Model进行的修改有可能会对其他的View造成“连锁反应”,再加上各种异步回调,给代码调试造成了很大的困难,往往难以定位数据到底是被谁修改掉的。用专业一点的术语来讲,代码的“可预测性”非常差。因此,为了提高可预测性,很多人主张回归到“单向数据流”模式,其中的典型代表就是facebook的Flux框架。

4.Flux

其实Flux并不是什么新鲜事物,其背后还是经典的MVC思想,但是实现方式上有所不同。Flux的核心是“组件化+单向数据流“,下面逐一进行介绍。

4.1组件化

在传统的MVC设计中,Model中不仅要存储应用程序数据,还需要存储UI状态。另一方面,Controller中不仅要处理业务逻辑,还需要实现各种事件处理逻辑。如果把这部分内容抽出来,和View组合在一起,就变成了“组件”。这样一来,各个模块都可以各司其职,专注于自己的领域,代码的可读性和复用性都可以得到提高。

在实际编程中,一般把纯界面展示的View实现成一个“无状态组件”,在其上层再包装一个Controller-View(也可以称为Container),专门监听事件并更新数据,然后把数据作为props传递给View。这种编程模式可以最大程度地提高组件的可复用性。

4.2单向数据流

为了提高代码的可预测性,Flux采用单向数据流设计。这里引入了3个新概念:

  • Store:每个程序可以拥有多个Store,存储应用程序状态的不同部分。Store对View是只读的,只有Dispatcher可以通过Store注册的回调函数修改Store的内容

  • Action:当发生交互,需要修改Store内容时,需要发起一个Action,包含对应的type和payload

  • Dispatcher:当接收到Action时,会通过回调函数调用所有Store的,完成数据修改

当Store数据发生变化时,会发送一个事件,View或者Controller-View可以监听这个事件,然后完成界面刷新。整个过程是“单向”的,如果View想要继续修改Store,必须重新发起一个Action。

当然,除了View以外,服务器或者Web API也可以直接发送Action给Dispatcher,这就是为什么图中Dispatcher有两个输入的原因。

更为详细的Flux流程参见下图:

通过以上分析可以发现,所谓单向数据流并不是什么新鲜概念,实际上最最经典的MVC设计中,数据流就是单向的。虽然Flux官方宣称它们不是MVC,但我个人认为其实它实际想说的是MVVM,因为MVVM才是双向数据流。

当然,Flux也不是完美的,在多Store协同管理上存在一定的设计缺陷,这也是后来Redux出现的原因,且听下回分解。

最后,以一张思维导图结束本篇文章:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章