Redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。

三大核心

在 Redux 中,最为核心的概念就是 action 、reducer、store 以及 state,那么具体是什么呢?

  • Action:是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源
  • Reducer:指明如何更新 state
  • Store:把 action、Reducer 联系到一起的对象,负责维持、获取和更新state

数据流

严格的单向数据流是 Redux 架构的设计核心。

Redux 应用中数据的生命周期遵循下面 4 个步骤:

  • 调用 store.dispatch(action) 触发 action
  • Redux store 调用传入的 reducer 函数
  • 根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树
  • Redux store 保存了根 reducer 返回的完整 state 树

搭配 React

核心库:

1
2
3
4
5
6
7
react
react-dom
react-router
react-router-redux //利用react-router-redux提供的syncHistoryWithStore我们可以结合store同步导航事件
redux
react-redux
react-thunk/react-saga/redux-logger //middleware

目录结构:

1
2
3
4
5
6
7
8
9
10
├─app
│ ├─actions //redux动作生成器
│ ├─assets //静态资源
│ ├─compontens //UI组建
│ ├─containers //容器组件
│ ├─reducers
│ ├─routes
│ ├─store
│ └─utils //工具函数
└─dist //发布目录

不过使用过 Redux 的人会有这些痛点:难懂的 API、复杂的逻辑、过多的代码侵入。Redux 采用单一根节点、函数式编程、动作分离管理(似乎让项目很容易管理),这些都是 Redux 过于复杂的原因。然这里并不是说 Redux 不好。基于项目本身,寻找一个最适合的框架才是优的解决方案。

Mobx

MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展。

比起Redux,Mobx基于观察者模式,采用多节点管理数据,是一个很轻量、入手简单、代码耦合小的数据框架。

核心概念

数据流

MobX 为单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。

它由几个部分组成:Actions、State、Computed Values、Reactions。使用 MobX 将一个应用变成响应式的可归纳为以下步骤:

  • 通过事件驱动(UI 事件、网络请求…)触发 Actions
  • 在 Actions 中修改了 State 中的值,这里的 State 既应用中的 store 树(存储数据)
  • 然后根据新的 State 中的数据计算出所需要的计算属性(computed values)值
  • 响应(react)到 UI 视图层

Observable state(可被观察的状态)

MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。 通过使用 @observable 装饰器来给你的类属性添加注解就可以简单地完成这一切。这样改属性就变成了“被观察者”。

1
2
3
class Store {
@observable a = 'Hello Word!';
}

Observer(观察者)

observer 函数装饰器可以用来将 React 组件转变成响应式组件。 它用 mobx.autorun 包装了组件的 render函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。 observer 是由单独的 mobx-react 包提供的。

1
2
3
4
5
6
7
8
9
10
@observer
class Index extends Component {
render() {
return (
<p>
{this.props.Store.a}
</p>
)
}
}

这样 Index 组件就变成了一个响应式的组件(智能组件),当“被观察者”改变时,该组件就会自动更新。

componentWillReact (生命周期钩子)

React 组件通常在新的堆栈上渲染,这使得通常很难弄清楚是什么导致组件的重新渲染。 当使用 mobx-react 时可以定义一个新的生命周期钩子函数 componentWillReact。当组件因为它观察的数据发生了改变,它会安排重新渲染,这个时候 componentWillReact 会被触发。这使得它很容易追溯渲染并找到导致渲染的操作(action)。

inject(注入)

inject 函数装饰器可以将 Store 数据注入到组件当中。inject 是由单独的 mobx-react 包提供的。

1
@inject("store")

Computed values(计算值)

使用 MobX,可以定义在相关数据发生变化时自动更新的值。 通过 @computed 装饰器调用 的getter / setter 函数来进行使用。

1
2
3
4
5
6
7
class ItemsStore {
@observable items = []; @computed get total() {
return this.items.length;
}
}

当添加了一个新的 items 时,MobX 会确保 total 自动更新。

Action(动作)

action 是任一一段可以改变状态的代码。具体实现代码如下:

1
2
3
4
5
6
7
8
9
10
class HomeStore {
@observable num = 0; @action plus = () => {
this.num = ++this.num
}
@action minus = () => {
this.num = --this.num
}
}

如果是在严格模式:

1
2
import { useStrict } from 'mobx';
useStrict(true);

那么 MobX 会强制只有在动作之中才可以修改状态。对于任何不使用动作的状态修改,MobX 都会抛出异常。

异步 Action

action 包装/装饰器只会影响当前运行的函数,而不会影响当前函数调度(但不是调用)的函数! 这意味着如果你有一个 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,这些回调函数也应该包装在 action 中。可以使用 action 关键字来包装 promises 回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@action
fetchData = (url) => {
fetch(url).then(
action('fetchRes', res => {
return res.json()
})).then(
action('fetchSuccess', data => {
// TODO })).catch(
action('fetchError', e => {
// err
}))
}

异步 action 实现的方式还有多种,这里只列举了 action 关键子的模式

在 React 中使用 Mobx

在 React 中使用 MobX 需要用到 mobx-react。
其提供了 Provider 组件用来包裹最外层组件节点,并且传入 store 传递给后代组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from 'react';
import ReactDOM from 'react-dom';
import {useStrict} from 'mobx';
import {HashRouter as Router} from 'react-router-dom'
import {Provider} from 'mobx-react';
import * as stores from './store'; import App from './compontens/App' useStrict(true) // 不允许在动作之外进行状态修改 ReactDOM.render(
<Provider store={stores}>
<Router>
<App/>
</Router>
</Provider>, document.getElementById('root')
);

使用 @inject 给组件注入其需要的 store(利用 React context 机制);
通过 @observer 将 React 组件转化成响应式组件,它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, {Component} from 'react'
import {observer, inject} from 'mobx-react'
import {withRouter} from 'react-router-dom' @withRouter @inject('store') @observer
class App extends Component { render() {
return (
<div className="main">
//……
</div>
)
}
} export default App

其中 @withRouter 是 router 的 参数传入到组件中。

redux和mobx比较(二)的更多相关文章

  1. redux VS mobx (装饰器配合使用)

    前言:redux和mobx都是状态管理器,避免父级到子级再到子子级嵌套单向数据流,可以逻辑清晰的管理更新共享数据.(刷新页面redux储蓄数据即消失) 配置使用装饰器(使用高阶函数包装你的组件): n ...

  2. 谈谈 Redux 与 Mobx 思想的适用场景

    谈谈 Redux 与 Mobx 思想的适用场景 Redux 和 Mobx 都是当下比较火热的数据流模型,一个背靠函数式,似乎成为了开源界标配,一个基于面向对象,低调的前行. 函数式 vs 面向对象 首 ...

  3. redux和mobx比较(一)

    Redux vs Mobx 那么具体到这两种模型,又有一些特定的优缺点呈现出来,先谈谈 Redux 的优势: 数据流流动很自然,因为任何 dispatch 都会导致广播,需要依据对象引用是否变化来控制 ...

  4. 在react项目中使用redux or mobx?

    主要比较参数: 库体积,打包项目体积 开发体验 性能对比 在对比参数前首先分析一下redux和mobx的设计模式,redux和mobx都没有使用传统的mvc/mvvm形式,而且他们使用flux结构也略 ...

  5. 【译】Redux 还是 Mobx,让我来解决你的困惑!

    原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用了 Redux,但我最近都在使用 Mob ...

  6. redux和mobx入门使用

    redux和mobx入门使用 项目涉及技术 公共插件 create-react-app react-dom react-router react-router-dom react-hook redux ...

  7. Redux 入门教程(二):中间件与异步操作

    上一篇文章,介绍了 Redux 的基本做法:用户发出 Action,Reducer 函数算出新的 State,View 重新渲染. 但是,一个关键问题没有解决:异步操作怎么办?Action 发出以后, ...

  8. [Web 前端] mobx教程(二)-mobx主要概念

    cp from : https://blog.csdn.net/smk108/article/details/84960159 通过<Mobx教程(一)-Mobx简介>我们简单理解了Mob ...

  9. vuex、redux、mobx 对比

    出处:https://www.w3cplus.com/javascript/talk-about-front-end-state-management.html 其实大部分概念都差不多,只不过VUEX ...

随机推荐

  1. IIC设备驱动程序

    IIC设备是一种通过IIC总线连接的设备,由于其简单性,被广泛引用于电子系统中.在现代电子系统中,有很多的IIC设备需要进行相互之间通信 IIC总线是由PHILIPS公司开发的两线式串行总线,用于连接 ...

  2. 【转】如何利用多核CPU来加速你的Linux命令 — awk, sed, bzip2, grep, wc等

    如何利用多核CPU来加速你的Linux命令 — awk, sed, bzip2, grep, wc等   你是否曾经有过要计算一个非常大的数据(几百GB)的需求?或在里面搜索,或其它操作——一些无法并 ...

  3. springnodejs

    作者 : solq 最新文档请看 http://www.springnodejs.com 本文不再更新 blog : http://www.cnblogs.com/solq/p/3574640.htm ...

  4. 2016.6.21 -Dmaven.multiModuleProjectDirectory system propery is not set,Check $M2_HOME environment variable and mvn script match.

    eclipse中使用maven插件的时候,运行run as maven build的时候报错: -Dmaven.multiModuleProjectDirectory system propery i ...

  5. unity3D中使用Socket进行数据通信(一)

    公司今年3D产品的工作中心主要集中在提高产品深度上,通过对竞争产品的分析,发现我们的缺陷在于多人在线与后台管理部分,多人在线使用unity自带的Network能够搞定,后台部分前段时间主要研究了下Sq ...

  6. 公司的mysql-installer-community-5.7.19.0安装注意

    需要安装Microsoft Visual C++ 2013 Redistributable(x64) 和 Microsoft Visual C++ 2013 Redistributable(x86) ...

  7. 重读金典------高质量C编程指南(林锐)-------第五章 常量

    5.1  为什么需要常量 1)为了便于用户理解,增加程序的可读性. 2)在程序的很多地方都用到同一个常量,用某一个宏常量来定义可以减少错误. 规则:尽可能的使用含义直观明确的常量来表示程序中多次出现的 ...

  8. 指定UIView的某几个角为圆角

    如果需要将UIView的四个角全部设置为圆角,做法相当简单,只需要设置其layer的cornerRadius属性即可.而若要指定某几个角(小于4)为圆角,而别的角不变的时候,这种方法就不好用了.这种情 ...

  9. c# emit 动态实现接口

    using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace Te ...

  10. ios 推送证书没有密钥 解决方案【转载】

    注意事项: 1.keychains选择Login 2.2.在创建完CertificateSigningRequest.certSigningRequest可以看到Keys中该有你的私有秘钥 3.按文档 ...