redux实现原理
redux基本概念
基本概念
1.store
用来保存数据的地方,使用createStore来生成数据
store = createStore(fn)
2.state,通过拷贝store中的数据得到
state = store.getState()
3.action,用来表示视图发生的变化
action = {
type:'ADD_TODO',
payload:'Learn Redux'
}
4.Action Creator 用来生成action
const ADD_TODO = '添加 TODO'
function addTodo(text){
return {
type:ADD_TODO,
text
}
}
5.dispatch 用来发出action
store.dispatch(addTodo('Learn Redux'));
6.reducer 用来处理action,返回新的state
const reducer = function(state,action){
return new_state
}
createStore
function createStore(reducer,initState,enhancer){
//0.接收state,添加观察者
let state = initState
let listeners = []
//1. 获取state
function getState(){
return JSON.parse(JSON.stringify(state))
}
//2.造一个dispatch来发送action
function dispatch(action){
state = reducer(state,action)
listeners.forEach(linstener => linstener())
}
//3.添加订阅者
function subscribe(listener){
listeners.push(listener)
return function(){
listeners.filter(item => item != listener)
}
}
return {
getState,
dispatch,
subscribe
}
}
combineReducer
//先拿到reducer
function combineReducer(reducer){
//把state和action交给reducer处理
return (state={},action) => (
//拿到对应reducer的处理结果在把原来的属性拷贝到新对象上
Object.keys(reducer).reduce((cur,key) => {
cur[key] = reducer[key](state[key],action)
return cur
},{})
)
}
bindActionsCreators
function bindActionsCreators(actions,dispatch){
//先拿到actions和dispatch
return Object.keys(actions).reduce((obj,key)=>{
obj[key] = function(){
//等执行的时候在调用真正的actions和dispatch
dispatch(actions[key].apply(null,arguments))
}
return obj
},{})
}
ApplyMiddleware

1.在action之后redecer处理之前
中间件的执行过程
const middleware (dispatch) => (
(action) => {
console.log('middleware')
dispatch(action)
console.log('after middleware')
}
)
const middleware1 (dispatch) => (
(action) => {
console.log('middleware1')
dispatch(action)
console.log('after middleware1')
}
)
// middleware -> middleware1 -> action -> middleware1 -> middleware
compose函数的虹吸现象

//先执行栈顶的middleware然后回流到栈底的middleware
const compose = (middlewares) => (
middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
)
中间件的实现
const middleware1 = dispatch => (
action => {
console.log('middleware1')
let res = dispatch(action)
console.log('after middleware1')
return res
}
)
const middleware2 = dispatch => (
action => {
console.log('middleware2')
let res = dispatch(action)
console.log('after middleware2')
return res
}
)
const middleware3 = dispatch => (
action => {
console.log('middleware3')
let res = dispatch(action)
console.log('after middleware3')
return res
}
)
let middlewares = [middleware1,middleware2,middleware3]
const compose = middlewares => middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
const dispatch = (action) => {
console.log(`action: ${action}`)
return action
}
//这是最后一个中间件,调用它将返回第一个中间件
const afterDispatch = compose(middlewares)(dispatch)
const testAction = args => ({
type:"ACTION_TEST",
args
})
afterDispatch(testAction('plus!'))
applyMiddleware
const compose = middlewares => middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
//1.接收中间件
export default function applyMiddleware(...middlewares){
//2.接收store方法
return function(createStore){
//3.接收reducer
return function(reducer){
let store = createStore(reducer)
let dispatch
let middlewareAPI = {
getState:store.getState,
dispatch:action => dispatch(action)
}
//把state和dispatch方法传给中间件的一个函数
middlewares = middlewares.map(middleware => middleware(middlewareAPI))
//将dispatch传入中间件,把dispatch传给最后一个中间件,把最后一个中间件的第2个函数传给上一个函数,虹吸
dispatch = compose(...middlewares)(store.dispatch)
return {
...store,
dispatch //先执行middleware1
}
}
}
}
react-redux
Provider
class Provider extends React.Component{
//静态属性childContextTypes声明提供给子组件的Context对象的属性,并实现一个实例getChildContext方法,返回一个代表Context的纯对象 (plain object) 。
static childContextTypes = {
store:propTypes.object.isRequired
}
getChildContext(){
return {
store:this.props.store
}
}
render(){
return this.props.children
}
}
Connect
function Connect(mapStateToProps,mapDispatchToProps){
return function(WrapedComponent){
class ProxyComponent extends React.Component {
//子组件需要通过一个静态属性contextTypes声明后,才能访问父组件Context对象的属性,否则,即使属性名没写错,拿到的对象也是undefined。
static contextTypes = {
store:propTypes.object
}
constructor(props,context){
super(props,context)
this.store = context.store
//初始化state
this.state = mapStateToProps(
this.store.getState()
)
}
componentWillMount(){
//当state发生变化的时候通过setState更新组件的变化
this.unsubscribe = this.store.subscribe(()=>{
this.setState(mapStateToProps(this.store.getState()));
});
}
componentWillUnmount(){
//当组件删除的时候取消监听state的变化
this.unsubscribe();
}
render(){
let actions = {}
if(typeof mapDispatchToProps == 'function'){
actions = mapDispatchToProps(this.store.disaptch);
}else if(typeof mapDispatchToProps == 'object'){
actions = bindActionCreators(mapDispatchToProps,this.store.dispatch);
}
return <WrapedComponent {...this.state} {...actions}/>
}
}
return ProxyComponent
}
}
redux实现原理的更多相关文章
- 轻松理解Redux原理及工作流程
轻松理解Redux原理及工作流程 Redux由Dan Abramov在2015年创建的科技术语.是受2014年Facebook的Flux架构以及函数式编程语言Elm启发.很快,Redux因其简单易学体 ...
- redux原理
Redux实现原理 不同组件需要依赖同一个数据的时候,就需要状态提升至这些组件的根组件. redux是状态统一管理工具,需要使用它的原因是: 组件之间通信统一管理,方便代码维护. React中有一个特 ...
- 一起学习造轮子(二):从零开始写一个Redux
本文是一起学习造轮子系列的第二篇,本篇我们将从零开始写一个小巧完整的Redux,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Promises/A+,Red ...
- 揭开redux,react-redux的神秘面纱
16年开始使用react-redux,迄今也已两年多.这时候再来阅读和读懂redux/react-redux源码,虽已没有当初的新鲜感,但依然觉得略有收获.把要点简单写下来,一方面供感兴趣的读者参考, ...
- 借鉴redux,实现一个react状态管理方案
react状态管理方案有很多,其中最简单的最常用的是redux. redux实现 redux做状态管理,是利用reducer和action实现的state的更新. 如果想要用redux,需要几个步骤 ...
- 带着问题看redux源码
前言 作为前端状态管理器,这个比较跨时代的工具库redux有很多实现和思想值得我们思考.在深入源码之前,我们可以相关注下一些常见问题,这样带着问题去看实现,也能更加清晰的了解. 常见问题 大概看了下主 ...
- 十分钟理解Redux核心思想,过目不忘。
白话Redux工作原理.浅显易懂. 如有纰漏或疑问,欢迎交流. Redux 约法三章 唯一数据源(state) 虽然redux中的state与react没有联系,但可以简单理解为react组件中的th ...
- 对 Redux 一头雾水?看完这篇就懂了
首先,学习 Redux 可能会很困难 当你终于学会了如何使用 React,也有了自己去构建一些应用的信心,那会是一种非常棒的感觉.你学会了管理状态,一切看起来井井有条.但是,很有可能这就到了你该学习 ...
- react中redux的理解
定义 redux可以看作是flux的进阶版,主要用于react中公共状态(数据)的管理 redux底层原理 redux有一个createStore方法,这个方法用户创建公共存储空间,createSto ...
随机推荐
- 解决 sublime text 3 there are no packages available for installation 错误
重装win7 系统后,使用sublime text 3 出现下面的错误提示: 经过摸索,解决方案如下: 第一种方法: 是因为 ipv6 的问题,导致无法访问 sublime 官网,解决方法: 在 ho ...
- 记一次升级Ubuntu内核
uname -a 查看当前使用内核版本 升级指定内核 apt-get install linux-image-4.4.0-131-generic dpkg --get-selections | ...
- oracle创建表空间、用户、权限
原链接:https://www.cnblogs.com/wxm-bk/p/6510654.html oracle 创建临时表空间/表空间,用户及授权 1:创建临时表空间 create tempor ...
- 50.RocketMQ (quickstart)
要多给下属表功,绝不能抢功. 1.订阅消息 /** * Copyright (C) 2010-2013 Alibaba Group Holding Limited * * Licensed under ...
- PCA简单实现
''' 总结一下PCA的算法步骤: 设有m条n维数据. 1)将原始数据按列组成n行m列矩阵X 2)将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值 3)求出协方差矩阵C=1/m*(XX ...
- Python全栈开发:list、元祖常用方法操作
列表[] 索引与切片#例题#li = ['yijiajun',[1,3,5,7,9],'zhangliang','zhaoritian','sunwukong'] # #例子1 找出列表中索引为0的元 ...
- scp 一次拷贝多个文件
用正则表达式去匹配即可, scp *.tar root@11.11.11.12:/root/ 拷贝当前目录下的所有tar类型的文件到服务器上
- 开源:我的Android新闻客户端,速度快、体积小、支持离线阅读、操作简便、内容展现形式丰富多样、信息量大、功能全面 等(要代码的留下邮箱)
分享:我的Android新闻客户端,速度快.体积小.支持离线阅读.操作简便.内容展现形式丰富多样.信息量大.功能全面 等(要代码的留下邮箱) 历时30天我为了开发这个新闻客户端APP,以下简称觅闻 h ...
- (转)Mysql数据库主从心得整理
Mysql数据库主从心得整理 原文:http://blog.sae.sina.com.cn/archives/4666 管理mysql主从有2年多了,管理过200多组mysql主从,几乎涉及到各个版本 ...
- JavaScript数据结构-7.链表
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...