Redux的createStore实现

  使用过react的同学应该对Redux这个东西有所了解。他是一种全局状态管理的思想(对, 这里我觉得它是一种思想, 因为对于React来说, 其实Redux内部并没有什么需要与React兼容的东西, react-redux 库里才有), 它信奉的是:

  • 唯一数据仓库
  • 只能读取
  • 数据改变只能通过纯函数进行

  这其实对我们是一种约束, 毕竟我们就算引入了Redux, 也能使用this.props去进行父子组件数据传输, 但是当你需要非父子组件的通信的时候, 里面的数据流动会非常难以捉摸, 所以我们使用Redux。

在React中集成Redux时, 在程序的入口处,我们可以看到这样的一段代码

// 这里的todoApp是一个Reducer函数,接受的是state和actions
const store = createStore(todoApp)

  在我们的react使用单一仓库的时候,能看到一下的一些类似的代码,从中我们能看到,我们本组件的state是通过this.state = store.getState()所创建的, 那么我们的store是一个对象,里面有一个getState函数能够返回内部的state,同时这个state是需要持久保存的,所以我们大概能有一些思路。

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 const dispatch = (action) => {
state = reducer(state, action)
listeners.forEach(listener => listener())
} const subscribe = (listener) => listeners.push(listener) // 这里初始化dispatch的原因是在这之前,state是为null的
//所以我需要传一个不存在的action去reducer里面,拿到最默认的那个defaultState
//这个defaultState写在reducer的那个文件里面
dispatch({});
return {
dispatch,
subscribe,
getState,
}
}

  所以刚才的分析, 我们需要创建一个函数对象createStore

  1、createStore里面用闭包的方法储存了一个state,我们程序用到的仓库就是这个、还储存有一个函数数组listeners,用于储存用户定义的函数(一般是用更新后的仓库重置this.state),因为我其实有多个页面都注册了一个订阅函数, 所以使用函数数组, 当需要分发时取出来取出来调用即可。

  2、createStore需要定义一个方法getState能够拿到state,这样就能够在React中使用this.state = store.getState()来初始化state并进行读取了

  3、createStore还需要定义一个方法dispatch, 因为redux不能直接修改state的值, 所以必须通过dispatch函数,传入action, 然后带着state直接传入reducer里, reducer会传回修改后的state

  4、createStore再需要定义一个方法subscribe, 这是用来监听修改的函数, 在使用时, 绑定一个函数, 这个函数里会在外界获得state。所以这个函数应该接收一个函数, 然后push入一个队列里, 可是应该实时监听的, 为何要置入队列呢?这里我的理解是, 在一开始就将"外界重新获得state"这个函数置入队列, 类似Promise我承诺会使用这个函数。所以这个函数的使用应该放置在dispatch里面, 它传回一个state后, 做的事情是将所有队列中的"外界重新获得state"函数全部拿出来执行一遍。

  所以这个createStore函数的效果很明显了,getState用于获取当前state, subscribe用于给外界设置监听并将监听函数储存在createStore函数的属性中, 每次用户通过dispatchaction来修改state的时候, 将里面所有的监听函数拿出来执行一遍。而dispatch则是用来执行state修改的, 毕竟这个函数不允许使用setState这类的函数。

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

Redux的createStore实现的更多相关文章

  1. redux之createStore方法底层封装模拟

    首先在看代码之前让我们一起回顾下redux的思想吧   首先redux就是一个MVC思想的框架,他总体是遵循数据的单向流动自顶向下流动 在我们仓库中有一个initState用来存储着我们的初始数据 另 ...

  2. redux中createStore方法的默认参数

    一般使用方法: createStore(reducer, applyMiddleware(thunk)) 传递默认参数: createStore(reducer, defaultState, appl ...

  3. Redux源码分析之createStore

    接着前面的,我们继续,打开createStore.js, 直接看最后, createStore返回的就是一个带着5个方法的对象. return { dispatch, subscribe, getSt ...

  4. 实例讲解react+react-router+redux

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  5. redux介绍与入门

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...

  6. Redux介绍及基本应用

    一.Redux介绍  Redux的设计思想很简单,就两句话: Web应用是一个状态机,神力与状态是一一对应的 所有的状态,保存在一个对象里面 二.Redux基本概念和API Store Store就是 ...

  7. redux学习笔记

    中文api:http://cn.redux.js.org/docs/react-redux/troubleshooting.html 3.6 Reducer Store 收到 Action 以后,必须 ...

  8. 深入Redux架构

    关于redux 之前写了一篇通过一个demo了解Redux,但对于redux的核心方法没有进行深入剖析,在此重新总结学习,完整的代码看这里.(参考了React 技术栈系列教程) 什么情况需要用redu ...

  9. 【前端】react and redux教程学习实践,浅显易懂的实践学习方法。

    前言 前几天,我在博文[前端]一步一步使用webpack+react+scss脚手架重构项目 中搭建了一个react开发环境.然而在实际的开发过程中,或者是在对源码的理解中,感受到react中用的最多 ...

随机推荐

  1. 吴裕雄--天生自然python学习笔记:Python3 输入和输出

    输出格式美化 Python两种输出值的方式: 表达式语句和 print() 函数. 第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用. 如果你希望输出的 ...

  2. C\C++ 位域操作

    几篇较全面的位域相关的文章: http://www.uplook.cn/blog/9/93362/ C/C++位域(Bit-fields)之我见 C中的位域与大小端问题 内存对齐全攻略–涉及位域的内存 ...

  3. IOUtils和FileUtils的学习笔记

    pom文件导入依赖import org.apache.commons.io.FileUtils; <dependency> <groupId>commons-io</gr ...

  4. Luogu_2279_[HNOI2003]消防局的设立

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  5. Python---11模块

    在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很 ...

  6. JavaScript值类型和引用类型有哪些

    JavaScript值类型和引用类型有哪些 (1)值类型:数值.布尔值.null.undefined. (2)引用类型:对象.数组.函数.

  7. Golang: chan定义问题(7)

    通常都是定义读写双向的 chan,定义单向 chan 问题. 专栏的介绍可以参考 <GotchaGolang专栏>,代码可以看<宝库-Gotcha>. 通过 只写 chan 传 ...

  8. docker学习读书笔记-一期-整理

    0.Docker - 第零章:前言 1.Docker - 第一章:Docker简介 2.Docker - 第二章:第一个Docker应用 3.Docker - 第三章:Docker常用命令 4.Doc ...

  9. acedCommandS 实现pedit命令

    acedCommandS(RTSTR, _T("PEDIT"),                RTSTR, _T("M"),                R ...

  10. 使用python抓取汽车之家车型数据

    import requests import pymysql HOSTNAME = '127.0.0.1' USERNAME = 'root' PASSWORD = 'zyndev' DATABASE ...