博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redux执行流程梳理
阅读量:6399 次
发布时间:2019-06-23

本文共 3406 字,大约阅读时间需要 11 分钟。

写在前面

不管看多少篇源码解析,感觉都不如自己写一篇记得牢。

Redux干啥用的

在不看一切解析之前,我把redux当初页面的临时数据库使用。不论页面包含多少个组件,嵌套多深,是否使用react-router,是否使用bundle-loader异步加载,把需要的所有数据都存在全局一个变量上(这个变量也就是redux创造的store),这样就不用费心巴拉的实现组件之间数据传递了,尤其是嵌套层级深的组件之间,使用props传递数据简直实在加工时。所有的组件都从store上拿数据,避免传递。而当数据有更新时,我们只需要维护这一个变量(store)即可。

createStore: 创建"全局store"

本方法接收reducer, preloadedState, enhancer三个参数。

preloadedState参数是我们将创造的store的默认值。

reducer是一个纯函数,他的作用可以这样理解:reducer(oldStore,action) => newStore, 传入老的store和action,reducer执行后会输出新的store。

代码104行:

var currentReducer = reducer;var currentState = preloadedState;var currentListeners = [];复制代码

createStore执行时内部会创建上述变量,currentState保存的就是我们需要的"全局store"。currentListeners保存的监听函数(下面会说干啥用的)。

代码121行:

function getState() {    return currentState;}复制代码

本方法就是获取最新的store的。

下面有这个一个问题

现在全局store已经有了,那么react的各级组件怎么使用这个全局变量呢?我的第一反应是直接window.store调用呗,这样多简单粗暴。但是事实上react并没有采用这种方法,具体原因没想到太多,基于能不使用全局变量就不使用的原则,忽略。

react使用redux创造的store是通过getChildContext()方法

根组件Article:

let store = createStore(reducer,{data1:0})class Article extends PureComponent {    constructor(props) {        super(props);    }        getChildContext(){    	return {    		store:store    	}    }}Article.childContextTypes = {	store:PropTypes.object,};复制代码

通过getChildContext方法,Article组件的所有子孙组件都可以通过 let store = this.context.store获取到store变量。 子组件List:

class List extends PureComponent {	state = {		name:'list1'	}	constructor(props,context) {        super(props,context);    }	componentDidMount(){		let store = this.context.store		this.updateStore()		this.unsubscribe = store.subscribe(()=>{			console.log('list1 触发回调')			this.updateStore()		})	}	updateStore=()=>{		let store = this.context.store		this.setState({			...this.state,			...store.getState(),		})	}}List.contextTypes = {	store:PropTypes.object,}复制代码

这些所有的子孙组件都接收到store这个变量了,并且都保存在各自的this.state上

下面问题又来了

现在所有的组件都那个store了,但是如果这个store改变了,所有的子孙组件接收的store也就"过时"不是最新的了,如何解决这个问题,方法时在每个调用store的地方都注册监听函数,监听函数里将最新的store赋给this.state。一旦store更改,执行所有的监听函数。实现这个功能的就是subscribe方法

代码121行:

function subscribe(listener) {if (typeof listener !== 'function') {  throw new Error('Expected listener to be a function.');}// 本方法会形成一个闭包,所以isSubscribed这个变量会一直保存var isSubscribed = true;ensureCanMutateNextListeners();nextListeners.push(listener);return function unsubscribe() {  if (!isSubscribed) {    return;  }  isSubscribed = false;  ensureCanMutateNextListeners();  var index = nextListeners.indexOf(listener);  nextListeners.splice(index, 1);};}复制代码

这个方法将收集到的listener(监听函数)push到nextListeners数组中,并返回一个解除监听的方法。 用法也就是上面componentDidMount()里的

this.unsubscribe = store.subscribe(()=>{	console.log('list1 触发回调')	this.updateStore()})复制代码

下面问题又来了

现在监听事件有了,那么以何种方式触发?redux采用dispatch一个action的方式触发监听,当dispatch一个action时,store会先更新成最新的,然后循环执行nextListeners中所有的监听事件,简单又粗暴。(题外话:这使得在一些复杂应用情况下会造成部分性能问题)

代码198行:

function dispatch(action) {    ...    try {      isDispatching = true;      currentState = currentReducer(currentState, action);    } finally {      isDispatching = false;    }    var listeners = currentListeners = nextListeners;    for (var i = 0; i < listeners.length; i++) {      var listener = listeners[i];      listener();    }    return action;复制代码

}

现在就可以直观看出reducer函数是干啥用的了,输入原来的state和action,输出新的state(就是上面说的store)。原理就像:

function reducer(state,{
type,data}){ if(type === 'add') { return state+data } } let newState = reducer(1,{
type:'add',data:2}) ====> 3复制代码

到这里大致流程已经走完,下节梳理中间件机制。。。给自己看

转载地址:http://plyea.baihongyu.com/

你可能感兴趣的文章
.NET源代码的内部排序实现
查看>>
解决Strict Standards: Only variables should be passed by reference
查看>>
解决JBoss只能通过localhost(127.0.0.1)而不能通过IP访问
查看>>
MS SQL处理双引号(DoubleQuote)函数
查看>>
[智能架构系列]什么是Buddy智能开发框架
查看>>
三十一、关于android camera setParameters出错
查看>>
【收藏】QCIF、 CIF、2CIF、DCIF、D1(4CIF)格式介绍
查看>>
hdu 3836 Equivalent Sets (tarjan缩点)
查看>>
一些iOS高效开源类库(转)
查看>>
JAVA编程心得-JAVA实现CRC-CCITT(XMODEM)算法
查看>>
C# DES加密
查看>>
浅谈Oracle分区表之范围分区
查看>>
IBM Tivoli NetView网管软件实战
查看>>
IPSec逻辑体系架构
查看>>
Exchange 2013部署系列之(六)配置邮件流和客户端访问
查看>>
List of Free Programming books
查看>>
思考Android架构(二):像Android框架,如何(How-to)吸引开发者来使用它呢?
查看>>
在html中,怎么获取当前页面body的高度,body是没有设置高度的,但是里面有内容...
查看>>
把 Array 转换成 Map
查看>>
MyBatis入门学习
查看>>