React+Redux 这种开发模式在公司跌跌撞撞的使用已经有五个月了。对这种开发模式进行一个MVC的总结算也是跟以前的知识结构做一个对接。
本文会按照当前项目中碰到的问题以及想澄清的一些概念来整理。
- 什么是MVC?为什么要MVC?
- React中的几个概念是干什么的?
- Redux中的几个概念是干什么的?
- React+Redux的MVC分层是什么样的?
1. 什么是MVC?我们为什么要MVC?
Model(模型)是应用程序中用于处理应用程序数据和逻辑的部分。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。
Model层主要有两个部分:1. DBObj定义数据库中对应的数据模型;2. 是逻辑的处理包括直接对数据库和网络数据的访问处理;
在我们的程序里面把这层也叫做业务层处理层。跟React和Redux的代码没有任何关系的一层。View(视图)是应用程序中处理数据显示的部分。视图层主要包括二个部分:1.视图层显示及交互逻辑;2.视图层的数据结构ViewObj, 包括React中的props和stats;
Controller(控制器)是响应视图层的事件和被动调用的事件(WebSocket发出的事件),根据不同的事件来组织不同业务逻辑处理,然后把处理结果反馈。而反馈的结果包括更新界面,更新数据模型。比如:视图层的数据更新,即Redux中的reducers。
为什么要用MVC?主要有三点:
- 使程序更简单更直观更容易理解;
- 在视图层的开发,是通过组件搭积木;
- 在控制层的开发,是用业务层的API搭积木。
2. React中的几个概念是干什么的?
- component
React.createClass方法就用于生成一个component ,然后像插入普通 HTML 标签一样,在网页中插入这个组件。组件的用法与原生的 HTML 标签完全一致。 - props
组件可以任意加入属性的,比如 <HelloWord name="Scott"> ,就是 HelloWord 组件加入一个 name 属性,值为 Scott。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。
this.props 表示那些一旦定义,当前组件就不再改变的特性,但是父组件是可以去修改的。Redux是通过connect把数据绑定到React的props来更新界面数据的。 - state
用于用户互动时当this.state数据变化,自动调用 this.render 方法,从而触发重新渲染组件。this.state 是会随着用户互动而产生变化的特性。
用的了Redux后目前我们只用于存放界面显示控制及状态的数据。
讨论:
- props和state在组件定义和容器定义时使用区别?
- component的生命周期中的几个方法的使用包括:
Mounting(插入到 DOM中)
These methods are called when an instance of a component is being created and inserted into the DOM:
constructor()
componentWillMount()
render()
componentDidMount()
Updating(正在被重新渲染)
An update can be caused by changes to props or state. These methods are called when a component is being re-rendered:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
Unmounting(已移出真实 DOM)
This method is called when a component is being removed from the DOM:
componentWillUnmount()
3. Redux中的几个概念是干什么的?
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。Store对象包含所有数据
state 就是某个时间点的数据,就要对 Store的快照。
store.dispatch()是 View通过Redux connect中mapDispatchToProps方法发出 Action 以及被动调用事件时发出比如WebSocketServer。
Action函数是修改state的唯一入口,比如通过connect的mapDispatchToProps方法绑定到视图层的一个操作,或者是来自WebSocket的一个消息事件;Action函数最后通过store.dispatch() 发出的Action对象,表示 State 应该要发生变化了。
通常的做法是在Container层mapDispatchToProps方法中调用。
Action对象其中的type属性是必须的,表示 Action 的名称。其他属性可以自由设置。
Reducer 是个纯函数,它接受 Action对象 和当前 State 作为参数,返回一个新的 State。
纯函数是函数式编程的概念,必须遵守以下一些约束。
不得改写参数
不能调用系统 I/O 的API
不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
4. React+Redux的MVC分层是什么样的?
1.React-Redux库的组件
React-Redux 库将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。
- UI 组件(presentational component)因为不含有状态,UI 组件又称为"纯组件",即它纯函数一样,纯粹由参数决定它的值。
UI 组件有以下几个特征。
只负责 UI 的呈现,不带有任何业务逻辑
没有状态(即不使用this.state这个变量)
所有数据都由参数(this.props)提供
不使用任何 Redux 的 API
- 容器组件(container component)使用connect生成的
负责管理数据和业务逻辑,不负责 UI 的呈现
带有内部状态
使用 Redux 的 API
React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。
2.React-Redux库的connect
React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。
connect方法的完整 API 如下
import { connect } from 'react-redux'
const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps)(TodoList)
connect方法接受两个参数:mapStateToProps和mapDispatchToProps。
- mapStateToProps负责输入逻辑即将state映射到 UI 组件的参数(props);
- mapDispatchToProps负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。
3.React+Redux的MVC分层
** 视图层 ** React(component 、props(包括ViewObj)、state) (不能调用Redux的API)
** 控制层 ** Redux connect(输入逻辑,输出逻辑=> Action函数)(Page(由多个组件组成的页面))->Container
Redux Action函数(Call->Manager ->DBObj->store.dispatch()) (视图层和Server都可以调用Action函数)
Redux Reducer(DBObj->ViewObj->state) (控制显示数据更改)
** 模型层 ** Mangaer层 ->ManagerService -> ORM(DBObj) (不能调用React和Redux的API)
** 工具包 ** DBOper NetOper