在业务中一般 MVVM 框架一般都会配合上数据状态库(redux, mobx 等)一起使用,本文会通过一个小 demo 来讲述为什么会引人数据状态库。

从 MVC 到 MVVM 模式说起

传统 MVC 架构(如 JSP)在当今移动端流量寸土寸金的年代一个比较头疼的问题就是会进行大量的全局重复渲染。但是 MVC 架构是好东西,其对数据、视图、逻辑有了清晰的分工,于是前端 MVC 框架(比如 backbone.js) 出来了,对于很多业务规模不大的场景,前端 MVC 框架已经够用了,它也能做到前后端分离开发单页面应用,那么它的缺陷在哪呢?

拿 backbone.js 说,它的 Model 对外暴露了 set 方法,也就是说可以在不止一个 View 里修改同个 Model 的数据,然后一个 Model 的数据同时对应多个 View 的呈现,如下图所示。当业务逻辑过多时,多个 Model 和多个 View 就会耦合到一块,可以想到排查 bug 的时候会比较痛苦。

针对传统 MVC 架构性能低(多次全局渲染)以及前端 MVC 框架耦合度高(Model 和 View) 的痛处,MVVM 框架完美地解决了以上两点。可以参阅之前写的 MVVM 框架解析之双向绑定

only MVVM

假设有这么一个场景,在输入框中查询条件,点击查询,然后在列表中返回相应内容。如下图所示:

假设用 react 实现,思路大体是先调用查询接口,调用成功后将获取到的数据通过 setState 存进 list 中,列表显示部分代码如下:

const Decorate = (ListComponent) => class extends Component {constructor() {super()this.state = { list: [] }}componentDidMount() {fetch('./list.json').then((res) => res.json()).then(result => this.setState({ list: result.data }))}render() {return (<ListComponent data={this.state.list} />)}
}
复制代码

接着往封装的 Decorate 组件里,传入无状态函数构建的 List 组件用来展示列表数据,代码如下:

function List(props) {return (<div>{props.data.map(r =><p key={r.id}>{r.content}</p>)}</div>)
}
复制代码

可以看到 List 组件相当于是 View 层,而封装的 Decorate 组件相当于是 Model 层。但是这么做还是把业务逻辑写进了组件当中。而我们期望的是能得到一个纯粹的 Model 层和 View 层。接着一起看看 Flux 架构模式是如何解决这个问题的。

引人 Flux 架构模式

Flux 架构模式的 4 个重要组成部分以及它们的关系如上图所示,下文会根据 dispatch,store, action, view 的顺序逐步揭开 Flux 架构模式的面纱。

从 Flux 的源码中可以看出 Dispacher.js 是其的核心文件,其核心是基于事件的发布/订阅模式完成的,核心源码如下:

class Dispatcher {...// 注册回调函数,register(callback) {var id = _prefix + this._lastID++;this._callbacks[id] = callback;}// 当调用 dispatch 的时候会调用 register 中注册的回调函数dispatch(payload) {this._startDispatching(payload);for (var id in this._callbacks) {this._invokeCallback(id);}}
}
复制代码

回顾下之前的目的:让 Store 层变得纯粹。于是定义了一个变量 comments 用来专门存放列表数据,在了解 Dispatcher 的核心原理之后,当调用 dispatch(obj) 方法时,就可以把参数传递到事先注册的 register 函数中,代码如下:

// commentStore.js
let comments = []
const CommentStore = {getComment() {return comments}
}dispathcer.register((action) => { // 调用 Dispatcher 实例上的 register 函数switch (action.type) {case 'GET_LIST_SUCCESS': {comments = action.comment}}
})
复制代码

以及 action 中的函数如下:

// commentAction.js
const commentAction = {getList() {fetch('./list.json').then((res) => res.json()).then(result =>dispathcer.dispatch({ // 调用 Dispatcher 实例上的 dispatch 函数type: 'GET_LIST_SUCCESS',comment: result.data}))}
}
复制代码

但是似乎少了点什么,当 GET_LIST_SUCCESS 成功后,发现还缺少通知到页面再次调用 CommentStore.getComment() 的能力,所以再次引用事件发布/订阅模式,这次使用了 Node.js 提供的 events 模块,对 commentStore.js 文件进行修改,修改后代码如下:

let comments = []
const CommentStore = Object.assign({}, EventEmitter.prototype, {getComment() {return comments},emitChange() {this.emit('change')},addListener(callback) { // 提供给页面组件使用this.on('change', callback)}
})appDispathcer.register((action) => {switch (action.type) {case 'GET_LIST_SUCCESS': {comments = action.commentCommentStore.emitChange() // 有了这行代码,也就有了通知页面再次进行调用 CommentStore.getComment 的能力}}
})
复制代码

剩下最后一步了,就是整合 store 和 action 进页面中,代码如下:

class ComponentList extends Component {constructor() {super()this.state = {comment: commentStore.getComment()}}componentDidMount() {commentStore.addListener(() => this.setState({ // 注册函数,上面已经提过,供 store 使用comment: commentStore.getComment()}))}render() {return (<div>{this.state.comment.map(r =><p key={r.id}>{r.content}</p>)}</div>)}
}
复制代码

小结

单纯以 mvvm 构建应用会发现业务逻辑以及数据都耦合在组件之中,引入了 Flux 架构模式后数据和业务逻辑得到较好的分离。但是使用 Flux 有什么缺点呢?在下篇 《聊聊 Redux 架构模式》中会进行分析,下回见。

本文实践案例已上传至 stateManage

系列博客,欢迎 Star

探索从 MVC 到 MVVM + Flux 架构模式的转变相关推荐

  1. iOS 开发中的 Flux 架构模式

    本文讲的是iOS 开发中的 Flux 架构模式, 在半年前,我开始在 PlanGrid iOS 应用程序中采用 Flux 架构(开发).这篇文章将会讨论我们从传统的 MVC 转换到Flux的动机,同时 ...

  2. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    本文转载自https://www.tianmaying.com/tutorial/AndroidMVC,原文作者周鸿博. 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开 ...

  3. MVC---Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    转载自: http://www.tianmaying.com/tutorial/AndroidMVC 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使 ...

  4. Android MVC ,MVP,MVVM 常见架构浅谈

    简述:其实任何架构的目的都是:提高开发效率,降低维护成本: MVC: Model: 负责处理数据逻辑,一般包括操作数据库,耗时网络操作等组成: View:负责处理视图: 一般是xml布局: Contr ...

  5. 架构模式:MVC与MVVM

    本文探讨如下几个问题: 什么是MVC 什么是MVVM MVC与MVVM对架构属性的影响 MVC实例SpringMVC MVVM实例Vue MVC.MVVM与Layer中的Model,Controlle ...

  6. 浅谈 MVC、MVP 和 MVVM 架构模式

    2019独角兽企业重金招聘Python工程师标准>>> 谈谈 MVX 中的 Model 谈谈 MVX 中的 View 谈谈 MVX 中的 Controller 浅谈 MVC.MVP ...

  7. Flux架构思想在度咔App中的实践

    导读:为了应对视频编辑类工具应用复杂的交互,度咔iOS借鉴了Flux架构模式的设计思想,参考有向无环图的拓扑概念,将事件进行集中化管理,从开发体验上实现了舒适清爽.容易驾驭的"单向流&quo ...

  8. 软件开发架构模式浅谈:一些思考和实践记录

    一 背景和问题 我个人平时会比较慎用"架构"这个词 一方面是觉得业界有很多架构大师和架构模式,而我的认知和实践有限: 另一方面是因为这个词看着挺高大上.有点务虚,如果不结合实际场景 ...

  9. 浅谈软件开发架构模式

    本文作者将介绍他对于软件开发架构模式的一些思考和实践. 背景和问题 我个人平时会比较慎用"架构"这个词 一方面是觉得业界有很多架构大师和架构模式,而我的认知和实践有限: 另一方面是 ...

最新文章

  1. 【重磅】吴恩达宣布 Drive.ai 自动驾驶汽车服务落地 理想就这样成了现实!
  2. ASP.NET 2.0 - 如何把上传的文件保存到数据库字段 (转自章立民CnBlogs)
  3. 无论腾讯是自主开放还是被开放,我们都表示欢迎和支持
  4. JavaSE(一)——HelloWorld
  5. Mybatis Plus——[Could not set property 'id' of '***' with value]解决方案
  6. request的简介和运行环境
  7. 经典编程问题之:选择排序、冒泡排序、汉诺塔游戏,均用js代码实现
  8. vue列表排序实现中的this问题
  9. 硬件开发者之路之——保护电路系列之输入电源端口的防护设计
  10. windows配置Hadoop开发环境
  11. 用JS代码输出101-200之间的素数
  12. 力扣——算法入门计划第十四天
  13. 单应性变换(Homography)的学习与理解
  14. 打字练习网站keybr.com
  15. 我的Java传承名单(不知为何以前的又没有了,幸亏有备份才可以又贴出来)
  16. 初创公司需要哪些部门_哪些初创公司在安全方面犯了错误
  17. Python基础学习笔记-4.组合数据类型
  18. jdk安装包解压后如何安装(jdk下载安装)
  19. 2020年国赛A题目思路(高教杯全国大学生数学建模竞赛)
  20. 打造APP引导页3D切换特效

热门文章

  1. Java语言的循环控制结构
  2. TCP粘包问题 转自CSDN
  3. Struts中乱码问题解决
  4. Enterprise Vault 系列 [CA和DA]
  5. 写一个比较全的进制转换函数--ic
  6. 0717PHP基础:面向对象
  7. jQuery之validate验证表单
  8. iOS多线程开发之GCD(基础篇)
  9. Photoshop 隐藏的快捷键
  10. HDU ACM 3177 Crixalis's Equipment