探索从 MVC 到 MVVM + Flux 架构模式的转变

本文首发于 my blog

在业务中一般 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.comment
      CommentStore.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

原文地址:https://www.cnblogs.com/MuYunyun/p/8442179.html

时间: 2024-07-30 08:03:37

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

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

来源: Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什么? 本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注意的问题. 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员

iOS学习之MVC,MVVM,MVP模式优缺点

为什么要关注架构设计? 因为假如你不关心架构,那么总有一天,需要在同一个庞大的类中调试若干复杂的事情,你会发现在这样的条件下,根本不可能在这个类中快速的找到以及有效的修改任何bug.当然,把这样的一个类想象为一个整体是困难的,因此,有可能一些重要的细节总会在这个过程中会被忽略. 分析三种模式的优缺点: MVC 即 Modal View Controller(模型 视图 控制器). 20 世纪 80年代为编程语言 Smalltalk-80 发明的一种软件设计模式 MVC 的几个明显的特征和体现: 

iOS开发&gt;学无止境 - 浅谈MVVM的架构设计与团队协作

李刚按:本文是青玉伏案写的一篇文章.相信大家对MVC耳熟能详,MVVM可能听说的相对少一些,这一篇文章将会想你阐述MVVM设计,还有团队协作的经验分享.如果你也觉得不错,就分享一下吧! demo:https://github.com/lizelu/MVVM 今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由 于本人项目经验有限,关于架构设

iOS开发之浅谈MVVM的架构设计与团队协作

今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与传统的MVC可谓是极为相似,也可以说是兄弟关系,也就是一家人了. 说道架构设计和团队

浅谈iOS中MVVM的架构设计与团队协作

一.小酌一下MVVM 在这呢也不赘述什么是MVC,神马又是MVVM了,在百度上谷歌一下一抓一大把,在这儿就简单的提上一嘴.下面的Demo用的就是MVVM的架构模式. Model层是少不了的了,我们得有东西充当DTO(数据传输对象),当然,用字典也是可以的,编程么,要灵活一些.Model层是比较薄的一层,如果学过Java的小伙伴的话,对JavaBean应该不陌生吧. ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代

浅谈iOS中MVVM的架构设计与团队协作【转载】

今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与传统的MVC可谓是极为相似,也可以说是兄弟关系,也就是一家人了. 说到架构设计和团队

IOS中 浅谈iOS中MVVM的架构设计与团队协作

今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与

MVC与MVVM设计模式理解

MVC设计模式(View和Model之间不能直接通信) MVC是一种架构模式,M表示Model,V表示视图View,C表示控制器Controller: Model负责存储.定义.操作数据(Struts中Service和Form): View用来展示给用户,并且和用户进行交互: Controller是Model和View的协调者,Controller把Model中的数据拿过来给View使用.Controller可以直接与Model和View进行通信,而View不能与Controller直接通信.,

iOS架构模式--解密 MVC,MVP,MVVM以及VIPER架构

在 iOS 中使用 MVC 架构感觉很奇怪? 迁移到MVVM架构又怀有疑虑?听说过 VIPER 又不确定是否真的值得切换? 相信你会找到以上问题的答案,如果没找到请在评论中指出. 你将要整理出你在 iOS 环境下所有关于架构模式的知识.我们将带领大家简要的回顾一些流行的架构,并且在理论和实践上对它们进行比较,通过一些小的例子深化你的认知.如果对文中提到的一些关键词有兴趣,可以点击连接去查看更详细的内容. 掌控设计模式可能会使人上瘾,所以要当心,你可能会对一些问题清晰明了,不再像阅读之前那样迷惑,