❝做者:米卡node
❞
使用过react的同窗应该对Redux这个东西有所了解。他是一种「全局状态管理」的思想(对, 这里我以为它是一种思想, 由于对于React来讲, 其实Redux内部并无什么须要与React兼容的东西, react-redux 库里才有), 它信奉的是:react
这其实对咱们是一种约束, 毕竟咱们就算引入了Redux, 也能使用this.props
去进行父子组件数据传输, 可是当你须要非父子组件的通讯的时候, 里面的数据流动会很是难以捉摸, 因此咱们使用Redux。redux
在React中集成Redux时, 在程序的入口处,咱们能够看到这样的一段代码数组
// 这里的todoApp是一个Reducer函数,接受的是state和actions const store = createStore(todoApp) 复制代码
在咱们的react使用单一仓库的时候,能看到一下的一些相似的代码,从中咱们能看到,咱们本组件的state
是经过this.state = store.getState()
所建立的, 那么咱们的store
是一个对象,里面有一个getState
函数可以返回内部的state
,同时这个state
是须要持久保存的,因此咱们大概能有一些思路。markdown
import React, { Component } from 'react' import store from '../../store' import { getIPData } from '../../store/actionCreators' class Page extends Component { // 个人初始化的一个组件,已经可以使用Redux了 constructor(props) { super(props); this.state = store.getState() store.subscribe(this.storeChange.bind(this)); } componentWillMount() { // 获取IP数据,这里是做为一个dispatch的例子 // 值得注意的是getIPData()返回的是一个带type字段的一个对象。 const action = getIPData(); store.dispatch(action); } render() { return ( <div className="page"> </div> ) } storeChange() { this.setState(store.getState()) } } export default Page 复制代码
接下来我将本身写的createStore
函数贴出来, 而后讲解。这个函数实现了大部分功能,可是对于中间件的处理这里并无可以实现,后面我应该会对其有一些补充。闭包
函数
export default function createStore(reducer){ let state = null; const listeners = []; const getState = () => state复制代码<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> dispatch = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">action</span>) =></span> { state = reducer(state, action) listeners.forEach(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">listener</span> =></span> listener()) } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> subscribe = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">listener</span>) =></span> listeners.push(listener) <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 这里初始化dispatch的缘由是在这以前,state是为null的</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//因此我须要传一个不存在的action去reducer里面,拿到最默认的那个defaultState</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//这个defaultState写在reducer的那个文件里面</span> dispatch({}); <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> { dispatch, subscribe, getState, } 复制代码}<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> dispatch = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">action</span>) =></span> { state = reducer(state, action) listeners.forEach(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">listener</span> =></span> listener()) } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> subscribe = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">listener</span>) =></span> listeners.push(listener) <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 这里初始化dispatch的缘由是在这以前,state是为null的</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//因此我须要传一个不存在的action去reducer里面,拿到最默认的那个defaultState</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//这个defaultState写在reducer的那个文件里面</span> dispatch({}); <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> { dispatch, subscribe, getState, } 复制代码
因此刚才的分析, 咱们须要建立一个函数对象createStore
oop
一、createStore
里面用闭包的方法储存了一个state
,咱们程序用到的仓库就是这个、还储存有一个函数数组listeners
,用于储存用户定义的函数(通常是用更新后的仓库重置this.state
),由于我其实有多个页面都注册了一个订阅函数, 因此使用函数数组, 当须要分发时取出来取出来调用便可。this
二、createStore
须要定义一个方法getState
可以拿到state
,这样就可以在React中使用this.state = store.getState()
来初始化state
并进行读取了spa
三、createStore
还须要定义一个方法dispatch
, 由于redux不能直接修改state
的值, 因此必须经过dispatch
函数,传入action
, 而后带着state
直接传入reducer
里, reducer
会传回修改后的state
。
四、createStore
再须要定义一个方法subscribe
, 这是用来监听修改的函数, 在使用时, 绑定一个函数, 这个函数里会在外界得到state
。因此这个函数应该接收一个函数, 而后push入一个队列里, 但是应该实时监听的, 为什么要置入队列呢?这里个人理解是, 在一开始就将"外界从新得到state"这个函数置入队列, 相似Promise我承诺会使用这个函数。因此这个函数的使用应该放置在dispatch
里面, 它传回一个state
后, 作的事情是将全部队列中的"外界从新得到state"函数所有拿出来执行一遍。
因此这个createStore
函数的效果很明显了,getState
用于获取当前state
, subscribe
用于给外界设置监听并将监听函数储存在createStore
函数的属性中, 每次用户经过dispatch
传action
来修改state
的时候, 将里面全部的监听函数拿出来执行一遍。而dispatch
则是用来执行state
修改的, 毕竟这个函数不容许使用setState
这类的函数。
这样, 咱们就简单了解并分析了Redux的基本原理并对其进行了重写, 就像我提到的, Redux实际上是一种约束的思想而出现, 这意味着在node中, 咱们一样也能使用Redux(虽然我以为可能没有必要)
本文使用 mdnice 排版