redux 单向数据流的由来

  1. Flux将应用分成四个部分;
  • view 视图层;
  • Action 视图层发出的消息;(改变store里面的数据)
  • Dispatch(派发器)
  • Store (数据层) : 用来存在应用的状态(数据),一旦发生变动,就要提醒view更新页面。

redux单向数据流:

具体详情请见阮一峰Flux架构入门

Action

  • 定义. Action 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。

  • 狭义的Action

let action = {type: 'ACTION_NAME',...
}
复制代码

注意: 一般 type 的内容使用 大写字母+下划线 的格式.

  • 广义的Action

    广义的 action 是指在中间件的支持下,dispatch 函数可以调用的数据类型,除了普通action之外,常见的有 thunk, promise 等。我们用常用的 thunk来举个例子

    什么叫thunk函数? 具体背景见阮一峰es6标准入门一书第17章Thunk函数的含义.在javaScript中函数将多参数函数替换成单参数的版本,且只接受回调函数作为参数。 例如:

var Thunk = function(fn){return function(){var args = Array.prototype.slice.call(arguments);return function(callback){args.push(callback);return fn.apply.(this,args);}}
}var readFileThunk = Thunk(fs.readFile);readFileThunk(fileA)(callback);
复制代码
Thunk函数版本的action:
复制代码
(dispatch, getState) => { //在函数体内可以使用 dispatch 方法来发射其他 action//在函数体内可以使用 getState 方法来获取当前的state
}
复制代码

ceateStore

通过该API创建一个store对象,该对象包含四个方法;

  1. getState();获取store中当前的状态。
  2. dispatch(action): 分发一个action,并返回这个action,这是唯一能改变store中数据的方式。
  3. subscribe(listener): 注册一个监听者,它在store发生变化时被调用。
  4. replaceReducer(nextReducer): 更新当前store里的reducer, 一般只会在开发模式中调用该方法。

redux middleware

  • Redux 是一个简单的同步数据流,当分发一个action时,reducer收到action后,更新state并通知view重新渲染。 当action发出后如果想要执行一些别的操作,该怎样处理,也就是说action发出后没有立即执行reducer,将redux变成异步. 这时就要借助中间件。

  • redux-middleware的数据流动.

  • 中间件的由来以及原理. 中间件的思想来源于koa. 核心思想:将middleware(函数)进行组合,将当前的middleware执行一遍作为参数传给下一个middleware去执行。

原理:

app.use((ctx, next) => {ctx.name = 'Lucy'next()
})app.use((ctx, next) => {ctx.age = 12next()
})app.use((ctx, next) => {console.log(`${ctx.name} is ${ctx.age} years old.`) // => Lucy is 12 years old.next()
})// ... 任意调用 use 插入中间件app.go({}) // => 启动执行,最后会调用 callback 打印 => { name: 'Lucy', age: 12  }
复制代码

ctx 参数就是 app.go 接受的对象。调用 app.go 其实会调用目标函数 app.callback,但是调用 app.callback 之前我们可以先让参数 ctx 通过一系列的中间件,最后才会传递给 app.callback。

使用 app.use 插入任意中间件,中间件是一个函数,可以被传入一个 ctx 和 next;调用 next 的时候会执行下一个中间件。如果不调用 next 会阻止接下来所有的中间件的执行,也不会执行 app.callback。

这里的app.use()就是一个实现中间件。

const app = {middleware:[],callback(){console.log(ctx);},use(fn){this.middleware.push(fn);},go(){const reducer = (next,fn,i)=> { fn(ctx,next)}this.middleware.reduceRight(reducer,this.callback.bind(this,ctx))();}
}
复制代码
  • redux的applyMiddleware的源码.
    function applyMiddle(){(next) => (reducer, initialState) => {let store = next(reducer,initialState);let dispatch = store.dispatch;let chain = [];let middlewarAPI = {getState:Store.getState,dispatch: (action) => { dispatch(action)}}chain = middlewares.map(middleware => middleware(middlewarAPI));dispatch = compose(...chain)(store.dispatch);return {...store,dispatch}}}
复制代码

一般这样应用middleware

const finalCreateStore = compose(applyMiddleware(...middleware)//DevTools.instrument()
)(createStore);const store = finalCreateStore(reducer);
复制代码

middleware的一般写法

const m1 = store => next => action => {let result = next(action);switch (action.type) {case APP_INCREMENT_LOADING:globalProgressBar.incrementLoading();break;case APP_DECREMENT_LOADING:globalProgressBar.decrementLoading();break;}return result;
};export default m1;复制代码

注:这里的compose函数请参考app.go或者参考上章FP一节; applyMiddle其实用了2个中间件的思想; 源码的详细解释:

作者个人博客: http://zhengchengwen.com 欢迎交流

转载于:https://juejin.im/post/5b17fd74f265da6e1d6ca9a5

redux 源码详解相关推荐

  1. 【Live555】live555源码详解(九):ServerMediaSession、ServerMediaSubsession、live555MediaServer

    [Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: ServerMediaSession.ServerMediaSubsession.Dy ...

  2. 【Live555】live555源码详解系列笔记

    [Live555]liveMedia下载.配置.编译.安装.基本概念 [Live555]live555源码详解(一):BasicUsageEnvironment.UsageEnvironment [L ...

  3. 【Live555】live555源码详解(八):testRTSPClient

    [Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的testRTSPClient实现的三个类所在的位置: ourRTSPClient.StreamClient ...

  4. 【Live555】live555源码详解(七):GenericMediaServer、RTSPServer、RTSPClient

    [Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: GenericMediaServer.RTSPServer.RTSPClient 14 ...

  5. 【Live555】live555源码详解(六):FramedSource、RTPSource、RTPSink

    [Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: FramedSource.RTPSource.RTPSink 11.FramedSou ...

  6. 【Live555】live555源码详解(五):MediaSource、MediaSink、MediaSession、MediaSubsession

    [Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的四个类所在的位置: MediaSource.MediaSink.MediaSession.MediaSub ...

  7. 【Live555】live555源码详解(四):Medium媒体基础类

    [Live555]live555源码详解系列笔记 7.Media Medai所依赖关系图 依赖Medai关系图 Media和UsageEnvironment关联图

  8. 【Live555】live555源码详解(二):BasicHashTable、DelayQueue、HandlerSet

    [Live555]live555源码详解系列笔记 3.BasicHashTable 哈希表 协作图: 3.1 BasicHashTable BasicHashTable 继承自 HashTable 重 ...

  9. 【Live555】live555源码详解(一):BasicUsageEnvironment、UsageEnvironment

    [Live555]live555源码详解系列笔记 类关系图 1.UsageEnvironment 详解 1.1 BasicUsageEnvironment BasicUsageEnvironment ...

最新文章

  1. python中索引是从什么开始_python索引从0开始,那负数索引算什么?三秋道果说python...
  2. sync.Once 的前世今生
  3. 安卓APP_ 布局(5) —— GridLayout网格布局
  4. 曾凭一己之力推动物理学发展,是清华大学最年轻教授,世界却欠他一个诺贝尔奖!...
  5. spring 面向接口编程_Spring面向方面的编程
  6. 在sql中将表建在别的构件中用什么语句_SQL实战
  7. whisper客服源码_深入ethereum源码-whisper协议解读
  8. FFmpeg4.0.2 over版本av_register_all()流程(二十九)
  9. uni的numberbox怎么用_jQuery EasyUI表单插件Numberbox数字框
  10. 把你的 Mac 从 Catalina 降级回 Mojave 系统的避坑指南
  11. ansys的kbc_ANSYS APDL 应用技巧
  12. 读《潜伏在办公室》第二季
  13. 第十一届“蓝狐网络杯”湖南省大学生计算机程序设计竞赛
  14. 曲终人散,我亦是行人。
  15. 直播平台开发,直播各个分类单例设计展示
  16. jquery.qrcode 批量打印
  17. 英创力电子IPO被终止:年营收10亿 深创投与红土是股东
  18. Informatica PowerCenter 简介(三)
  19. Mysql唯一索引 唯一约束
  20. 一行代码可以做什么?

热门文章

  1. mysql分区表达式_怎么定义 mysql hash分区使用的用 户定义的表达式
  2. mysql mysqld.sock_MySQL笔记-最简单的方法来解决找不到mysqld.sock文件的问题
  3. python慢为什么用的人还很多_为什么是所有人比python标准慢得多吗?
  4. 快速幂实现pow函数(从二分和二进制两种角度理解快速幂)
  5. leetcode1045. 买下所有产品的客户(SQL)
  6. python学习实例(5)
  7. addr2line 和 tombstone问题分析
  8. Linux内核 scatterlist介绍
  9. C++字符串的个人理解
  10. TDengine安装教程