zoukankan      html  css  js  c++  java
  • MVVM与Redux的概念类比

    先说MVC

    在这里插入图片描述
    在这里插入图片描述

    • 注意这里的箭头是单向的,单向的,单向的。

    • 优点:只具有单向的操作流,数据驱动。逻辑清晰。

    • 缺点:view监听Model较多,不可重用。controller不易于测试。

    • controller是MVC中的数据和视图的协调者,也就是在Controller里面把Model的数据赋值给View来显示(或者是View接收用户输入的数据然后由Controller把这些数据传给Model来保存到本地或者上传到服务器)

    MVP

    在这里插入图片描述

    • 所有操作都通过Presenter,Presenter,Presenter。

    优点:易于直接通过Presenter测试。view可重用。

    缺点:presenter不仅有业务逻辑,还要手动同步View和model,笨重。

    再说MVVM

    在这里插入图片描述

    • Model隐式更新View是通过Binder,Binder,Binder。

    • 优点:逻辑简化。可双向绑定。

    • 缺点:双向绑定可能会循环调用。依赖Binder质量。

    • MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。

    • Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。

    • Model: 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为

    • View: 用户操作界面。当ViewModel对Model进行更新的时候,会通过数据绑定更新到View

    • ViewModel: 业务逻辑层,View需要什么数据,ViewModel要提供这个数据;View有某些操作,ViewModel就要响应这些操作,所以可以说它是Model for View.

    总结: MVVM模式简化了界面与业务的依赖,解决了数据频繁更新。MVVM 在使用当中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。

    React

    发明了GraphQL专门用于高效提供数据,发明React实现对视图的组件化开发,启用第三方的Redux,处理组件间与前后端的通信。GraphQL,React与Redux分别对应MVVM的M,V,VM。

    React的更新是自顶向下的,为了减少不要必要的更新,内部提供了两个门闸,一个是只接受props的情况下, 通常会引发componentWillReceiveProps钩子,如果props, state( React16的getDerivedStateFromProps也发引发state改变 )及context 都没有改变, 这时不会更新子组件。另一种是setState的情况,由著名的shouldComponentUpdate来阻断更新。 React 50% 的性能优化手段都集中在shouldComponentUpdate的改良上,其中immutable机制必不可少,它只比较引用,不进行深比较。之前也有PureComponent,只比较对象的第一层属性差异。

    immutable机制可以通过immutable.js提供,也可以通过redux来提供。 redux的官网一开始罗罗索索说了这么多,就是讲如何构建一个store, store的每个属性是如何更新,一更新则直接修改它的上方所有容器,这种修改模型与immutable.js如出一辙。针对如何修改一个属性,于是搞出action type的概念,为了简化action创建的又发明了createAction, 怎么修改则引出了reducer的概念,然后触发修改又搞了一个dispatch方法。reducer是一个纯函数,有时我们需要一点点副作用,于是又提供了middleware。怎么就这么复杂呢!

    最大的原因还是为了immutable(不可变),于是需要纯函数。纯函数封装着一个不能被随意改修的数据,要访问它只能通过getState方法。于是我们能联想到,reducer纯函数不就是MVVM中的setter吗?! getState不就是getter吗?!
    在这里插入图片描述
    MVVM之所以轻松,是因为它将我们的模型对象全部进行遍历,一层层的遍历,将大部分属性转换为访问器属性。什么是访问器属性,就是用Object.defineProperty创建的属性,里面有setter, getter,多了两个方法,我们就有许多施展魔法的空间。setter用来更新视图,getter用来收集依赖。因为VM或叫store的属性大都会放到视图中,视图的{}或{{}}`这些位置上,这些位置可以换成视图刷新函数,因此 视图刷新函数要更新视图时,肯定会调用getter方法,于是这时就能确认这个方法与这个属性的关联关系,一个属性与多个视图刷新函数有关联,一对多,这正是观察者模式的用武之地。当我们再次改变这属性时,就可以遍历存放视图刷新函数所在的数组,实现视图的最小化刷新。

    redux 的问题在于,这个setter实现得太痛苦了。修改一个属性有不同的方式,于是有多个reducer, reducer写了一大堆分支,官方很nice教你用 switch,但还是很冗长。最后出现了redux-box, rematch这样的库,直接精简掉action的概念, 一个state就是对应一个model(想一下ng-model, v-model), model有原始值,有同步操作它的方法集(reducers),还有基于其上的异步操作方法集。

    export const count = {
      state: 0, // 它的初始值
      //reducers与effects都是各种操作count的方法,但是我们不应该有action概念,省得自己被绕进去
      reducers: {
        //reducers是一种纯正的setter,由于immutable的需求,要求传入旧的state, 返回新的state
        increment(state, payload) {
          return state + payload
        }
      },
      // 
      effects: (dispatch) => ({
        // effects是一种`异步`的setter,dispatch为访问器属性count所在的vm, 之所以单独出来,因为async/await需要特殊处理
        async incrementAsync(payload, rootState) {
          await new Promise(resolve => setTimeout(resolve, 1000))
          dispatch.count.increment(payload)
        })
      }
    }
    

    想获取这个model的数据,则直接通过 store.getState()。

    因此这时我们就可以绕开action,绕开了action也就不需要dispatch方法。 rematch通过一个dispatch对象,以经典的点点风格,就能找到要更新model,然后再在上面找到对应的setter

    import store from './index'
    const { dispatch } = store
    
    dispatch.count.increment(1)                       // state = { count: 2 }
    dispatch.count.incrementAsync(1)
    

    当一个属性发生改变时,我们要让程序做些什么,那么redux提供了一个subscribe方法。这东西不就是avalon/angular/vue的watch方法吗!

    当任何一个属性发生改变,我们要让程序做些什么,redux有一个middlewares机制,类似于koa的洋葱结构。这个在avalon有watch("*", fn), angular可以$watch一个对象,这样所有属性的变化都经会触发这回调。

    redux还有selector的概念,这个东西类似MVVM中的计算属性,它不存在于后端模型中,需要由已经有的属性组合出来。

    function mapStateToProps(state, props) {
    return {//author是动态计算出来的selector
        author: state.authors[props.authorId],
      };
    }
    

    因此如何能精简掉action的概念,简化调用流程,redux就能轻快起来。于是必须封装,于是有redux-saga, dva, rematch这样的东西。这些框架里面,个人是强烈建议使用rematch,没有太多魔术,处理异步是使用更易上手的async/await。anujs里面就使用一个改装版rematch做它的store。
    链接

    在这里插入图片描述
    翻译于 https://zhuanlan.zhihu.com/p/38025611

  • 相关阅读:
    java----使用socket模拟简单的http请求服务器,响应简单的文件请求操作
    Java实现的断点续传功能
    C 语言——分支和跳转
    C 语言——嵌套循环例子
    C 语言——循环
    C 语言——运算符、表达式和语句
    C 语言——字符串和格式化输入/输出
    C 语言——基础概论
    C 语言——开篇
    IDEA的安装教程
  • 原文地址:https://www.cnblogs.com/SiriusZHT/p/14310768.html
Copyright © 2011-2022 走看看