Redux的createStore实现

做者:米卡node

Redux的createStore实现

  使用过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>) =&gt;</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> =&gt;</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>) =&gt;</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>) =&gt;</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> =&gt;</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>) =&gt;</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, } 复制代码}

  因此刚才的分析, 咱们须要建立一个函数对象createStoreoop

  一、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函数的属性中, 每次用户经过dispatchaction来修改state的时候, 将里面全部的监听函数拿出来执行一遍。而dispatch则是用来执行state修改的, 毕竟这个函数不容许使用setState这类的函数。

  这样, 咱们就简单了解并分析了Redux的基本原理并对其进行了重写, 就像我提到的, Redux实际上是一种约束的思想而出现, 这意味着在node中, 咱们一样也能使用Redux(虽然我以为可能没有必要)

本文使用 mdnice 排版

相关文章
相关标签/搜索