什么是Redux

​ Redux我们可以把它理解成一个状态管理器,可以把状态(数据)存在Redux中,以便增、删、改。例如:

  1. 从服务器上取一个收藏列表,就可以把取回来的列表数据用Redux管理,多个页面共享使用,不用把数据传来传去。
  2. A页面改变了一个状态,B页面要收到通知,做相应的操作。

​ Redux是一个给JS应用使用的可预测的状态容器,也就是说结果是可预测的,每一次改动会有确定的结果,正如函数式编程思想里的相同的参数会返回相同的结果。

​ Redux的状态会存储在单一的数据源中(存储在对象树中),这样,读取和共享就非常方便,不必去考虑会取错。状态是只能直接读取的,不能直接修改,修改只能通过发送事件(action)统一处理,这样便于分析事件,也可以避免随处修改状态造成竞态条件。统一处理状态时用纯函数(reducers中的函数)来修改状态,这些函数只是一个勾子,当需要修改状态树时Redux会来调用,你可以编写不同的函数来处理不同action对应的状态,或者复用一个函数来处理多种action。

为什么要用

​ 简单来说就是使不易维护的数据变得维护简单,以小程序举例:多个页面要共享一套数据,而且这些数据是随时可能从网络上获取更新或增减的(如页面跳转时要带数据过去(非基本类型的数据),这时如果用app中的全局变量来暂存,存的变量多了,以后维护是个大麻烦,别人接手代码也会很烦恼。),还有一个地方的数据有改变,其他地方要收到通知等这些场景就可以使用Redux来做,如果你没有遇到这些问题,说明你的项目还没有到这些复杂的阶段,可以暂不考虑用Redux。

Redux的四个部件

 
redux-recycle
  • Action:action是一个事件,用来描述发生了什么事,例如用户点击了一个刷新按钮,就会产生一个获取最新数据的事件,Action就是用来标识这个事件的,Action是一个JS对象,拥有2个属性,一个type,一个data,type用来表示该action的类型,data为新的状态数据,既然是对象当然还可以带上一些其他的属性,在处理状态的时候使用。

  • Reducer:reducer是一个处理状态的函数,真正的状态数据处理就是在这个函数里,reducer接受两个参数,一个是修改前的状态(state)对象,一个是action。可以在reducer中判断action的type属性来确定是一个什么事件然后对state做相应的处理,并返回新的state。

  • Store:store是Redux的CPU,状态处理器,它提供了一些api给我们使用,如:

    • getState方法,可以获取到最新的状态对象树。
    • subscribe方法用来订阅状态的更新,该方法接受一个函数做为监听器,并会返回一个注销订阅的函数,以便我们在不需要订阅时注销改监听器。
    • dispatch方法用来分发事件,它接受一个action作参数,把事件发出去。
  • State:state是存储的数据,数据会以对象树的结构来管理,这里要注意,Store每次传给reducer的state是整个state对象树中对应该reducer名字(key)的子对象。

    ​ 事件发出后store会派reducer去处理事件,得到新的state,然后通知给各个监听器有新的变化(观察者模式)

    总体来说Redux就像是一个快递仓库(store),里面的货物(state)按地域分别存储,每当有一个新的货物进来(dispatch),处理程序或人员(reducer)就会去按地名(type)添加到仓库对应的位置,然后仓库通知(subscribe)快递员来取货物。

在小程序中使用Redux

先看目录结构:

project
|--app.js
|--libs
| |--redux-min.js
|--store
| |--actions
| | |--index.js
| | |--person.js
| |--reducers
| | |--index.js
| | |--person.js
| |--types
| | |--index.js
| | |--person.js
|--index.js

以存储人的年龄信息为例说一下步骤:

  1. 引入redux的lib,(redux-min.js)。文章最后有demo,libs文件夹里有可以直接使用的库,下载即可。

  2. 建立actions,reducers,types文件夹,这三个文件夹中的index.js只是为了在有多个文件时做统一导出,如不需要可去掉。

    action:

    // actions/person.js
    function personAction(data) {
    return {
    type: UPDATE_AGE,
    data
    }
    } export const ageChange = (age = 20) => {
    return personAction({ age: age })
    }

    reducers:

    // reducers/person.js
    const person = (state = {}, action) => {
    switch (action.type) {
    case UPDATE_AGE:
    return {
    ...state,
    age: action.data.age,
    }
    default:
    return state
    }
    } export default person

    types:

    // types/person.js
    export const UPDATE_AGE='UPDATE_AGE'
  3. 配置和创建redux:

    //store/index.js
    import {createStore,combineReducers} from '../libs/redux.min'
    import rootReducer from './reducers/index' export default function configAndCreateStore(){
    return createStore(combineReducers(rootReducer))
    }
  4. 在app.js中引入全局的store,并模拟1秒后通过redux修改年龄:

    import Store from './store/index'
    import { ageChange } from './store/actions/index' const $store = Store() App({
    onLaunch: function () {
    const that = this
    //1秒后修改年龄为25岁
    setTimeout(() => {
    that.store.dispatch(ageChange(25))
    }, 1000);
    },
    store: $store,
    globalData: {
    userInfo: null
    }
    })
  5. 在页面中订阅状态更改通知,获取新状态,页面生命周期结束时取消订阅:

    // pages/index.js
    
    //获取应用实例
    const app = getApp()
    onLoad: function () {
    this.unSubscribe = app.store.subscribe(() => {
    let person = app.store.getState().person
    console.log('store.subscribe person:', person)
    //这里要做个判断,当收到的状态与页面上已有的状态不一致时才去操作页面,可能会频繁收到订阅消息,要小心操作
    })
    },
    onUnload() {
    this.unSubscribe()
    },
    onShow(){
    //在任何时候都可以获取到当前最新的状态树,要灵活使用
    let person = app.store.getState().person
    console.log('store.subscribe person:', person)
    },

    任何时候都可以获取到当前最新的状态树,不一定要在订阅监听器函数中,要灵活使用。

我放在github上的demo: 点击查看

一些使用建议(以网络请求回数据为例)

  • 如果是多页面要共享的数据,建议用Redux来管理。
  • 如果修改数据后多处需要收到通知的情况,建议用Redux来管理。
  • 如果是一些一次性的数据(如收藏功能,返回结果就是一个收藏成功或失败,提示一下用户后就不再使用该结果了),未来不需要再利用,那么不建议用Redux来处理,直接去请求服务器处理结果就好。

扩展

​ Redux可以使用中间件来改变action的处理流程,可以分类处理action,如redux-thunk中间件,它可以使dispatch接受一个函数做为action,该函数中可以进行异步网络请求等,从而实现用Redux处理网络请求并管理返回结果。

作者:竹尘居士
博客:http://zhuchenju.com
公众号:竹尘居 (zhuchenju92)

作者:竹尘居士
链接:https://www.jianshu.com/p/91937040b8bd
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

九、小程序 Redux详解与在小程序中怎么使用(action和reducers)的更多相关文章

  1. Linux Bash命令关于程序调试详解

    转载:http://os.51cto.com/art/201006/207230.htm 参考:<Linux shell 脚本攻略>Page22-23 Linux bash程序在程序员的使 ...

  2. 小甲鱼PE详解之基址重定位详解(PE详解10)

    今天有一个朋友发短消息问我说“老师,为什么PE的格式要讲的这么这么细,这可不是一般的系哦”.其实之所以将PE结构放在解密系列继基础篇之后讲并且尽可能细致的讲,不是因为小甲鱼没事找事做,主要原因是因为P ...

  3. 小甲鱼PE详解之输入表(导出表)详解(PE详解09)

    小甲鱼PE详解之输出表(导出表)详解(PE详解09) 当PE 文件被执行的时候,Windows 加载器将文件装入内存并将导入表(Export Table) 登记的动态链接库(一般是DLL 格式)文件一 ...

  4. 小甲鱼PE详解之资源(PE详解11)

    原文出自:www.fishc.com 最近一直在安排第一届鱼C 学习班的事情,忙活了好一阵子,真是对不住大家,还大家久等了,这里要跟大家说声不好意思 ^_^ 今天我们来谈谈资源部分,资源部分可以说是 ...

  5. 嵌入式Linux应用程序开发详解------(创建守护进程)

    嵌入式Linux应用程序开发详解 华清远见 本文只是阅读文摘. 创建一个守护进程的步骤: 1.创建一个子进程,然后退出父进程: 2.在子进程中使用创建新会话---setsid(): 3.改变当前工作目 ...

  6. Android 颜色渲染(九) PorterDuff及Xfermode详解

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 颜色渲染(九)  PorterDuff及Xfermode详解 之前已经讲过了除ComposeShader之外Shader的全部子类 ...

  7. VS2010开发程序打包详解

    VS2010开发程序打包详解 转自:http://blog.sina.com.cn/s/blog_473b385101019ufr.html 首先打开已经完成的工程,如图: 下面开始制作安装程序包. ...

  8. 一个简单的C语言程序(详解)

    C Primer Plus之一个简单的C语言程序(详解) #include <stdio.h> int main(void) //一个简单的 C程序 { int num; //定义一个名为 ...

  9. “全栈2019”Java多线程第十九章:死锁详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. 一个项目里,httpclient竟然出现了四种

    有网友提问: 今年年初,到一家互联网公司实习,该公司是国内行业龙头.不过技术和管理方面,却弱爆了.那里的程序员,每天都在看邮件,查问题工单.这些问题,多半是他们设计不当,造成的.代码写

  2. 【分类算法】K近邻(KNN) ——kd树(转载)

    K近邻(KNN)的核心算法是kd树,转载如下几个链接: [量化课堂]一只兔子帮你理解 kNN [量化课堂]kd 树算法之思路篇 [量化课堂]kd 树算法之详细篇

  3. 【416】Ubuntu 配置

    修改桌面主题:How to Install Desktop Themes on Ubuntu 18.04 LTS 命令行显示短路径:怎样ubuntu下命令行终端显示短路径 gedit 扩展插件:Use ...

  4. (四)java对象的结构和对象的访问定位

    在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding). 一. 对象头 HotSpot虚拟机的对象 ...

  5. 手动mvn install指令向maven本地仓库安装jar包

    mvn install:install-file -DgroupId=imsdriver(jar包的groupId) -DartifactId=imsdriver(jar包的artifactId) - ...

  6. LSTM改善RNN梯度弥散和梯度爆炸问题

    我们给定一个三个时间的RNN单元,如下: 我们假设最左端的输入  为给定值, 且神经元中没有激活函数(便于分析), 则前向过程如下: 在  时刻, 损失函数为  ,那么如果我们要训练RNN时, 实际上 ...

  7. Django 数据库

    一.操作数据库 Django配置连接数据库: 在操作数据库之前,首先先要连接数据库.这里我们以配置MySQL为例来讲解.Django连接数据库,不需要单独的创建一个连接对象.只需要在settings. ...

  8. nginx静态资源设置缓存的方法

    nginx静态资源设置缓存的方法 直接加expires 30d; 就是就可以了 缓存时间30天完整如下 <pre> location / { root /home/www/wordpres ...

  9. [转载]Oracle中动态SQL详解

    1.静态SQLSQL与动态SQL Oracle编译PL/SQL程序块分为两个种:其一为前期联编(early binding),即SQL语句在程序编译期间就已经确定,大多数的编译情况属于这种类型:另外一 ...

  10. Linux程序Segmentation fault (core dumped)

    1 问题原因 Segmentation fault (core dumped)多为内存不当操作造成.空指针.野指针的读写操作,数组越界访问,破坏常量等.对每个指针声明后进行初始化为NULL是避免这个问 ...