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. iOS 5的文件存储策略应对

    苹果在iOS 5系统时,对app的文件存储提出了新的要求.从它的guildline来看,是推荐开发者尽量把app生成的文件放在Caches目录下的.原文如下: Only user-generated ...

  2. django中日志使用学习记录

    在setting中加入以下代码 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'verbose ...

  3. GLSL逐像素光照 【转】

    转载:http://blog.csdn.net/hgl868/article/details/7872414 逐像素的方向光(Directional Light per Pixel) 这一节将把前面的 ...

  4. mysql下监测数据库语句creating sort index时间过长的问题

    在一张单表5000W数据上进行数据查询时传入两个单列索引条件,进行组合索引查询时,如果最后有order by id排序,与去除该排序,性能差距接近两个数量级 结论:在使用列的默认排序时,不应该再ord ...

  5. JAVA Eclipse 创建android xml看不到预览怎么办

    电机安卓图标,设置为更低的API版本即可

  6. Activity 事件以及如何得到新打开Activity关闭后返回的数据

    1: package com.example.activity_basic; 2:   3: import android.os.Bundle; 4: import android.app.Activ ...

  7. SQLite可视化管理工具汇总

    版权声明:本文为博主原创文章,未经博主允许不得转载. 搜集了一些SQLite工具,在这里做个总结,有的工具用的多一些,有的只是简单试用,甚至未试用,所以有描述不当的还请回复指正,也欢迎补充完善! 20 ...

  8. .net 添加web引用和添加服务引用有什么区别?

    添加web引用和添加服务引用有什么区别, Add Service References 和 Add Web References 有啥区别? 参考 http://social.microsoft.co ...

  9. hdu 4862 KM算法 最小K路径覆盖的模型

    http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过全部的点一次而且只一次. 建图是问题: 我自己最初就把n*m 个点分别放入 ...

  10. cocos2dx-3.0(8)------Label、LabelTTF、LabelAtlas、LabelBMFont使用之法

    ----我的生活,我的点点滴滴!! 最后一个LabelBMFont了,字体图集LabelBMFont,LabelBMFont类是一个基于位图的字体图集.是一个包括全部你须要于坐标数据一起显示在屏幕上的 ...