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 ...
随机推荐
- Linux 中排除掉筛选的文件
以下命令以网站目录www为例做介绍,有时候更新网站的时候需要保留比如图片目录,或者其他目录就需要这样的操作 实例一: 删除文件夹内所有文件只保留一个文件命令 [root@linuxzgf www]# ...
- mybatis的执行流程
1.SqlSessionFactoryBuilder与SqlSessionFactory 我们一般在使用mybatis是都会通过new SqlSessionFactoryBuilder.build(. ...
- leetcode-209-长度最小的子数组
题目描述: 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = 7, nums ...
- Safari 不能播放Video ,Chrome等可以 问题解决。
1 原因分析 https://www.zhihu.com/question/41818719 2 代码实现 1 注意点: 请求时 : header中 range 请求多少长度 代码要返回相应的长度 ...
- java.lang.Exception: The server rejected the connection: None of the protocols were accepted
solution for this is from comment for https://issues.jenkins-ci.org/browse/JENKINS-29616. The follow ...
- Java 并发编程——Executor框架和线程池原理
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- springboot-2-ioc
在spring环境下, ioc(控制反转 和 DI (依赖注入) 是等效的, 主要体现一种组合的松耦合思想. spring Ioc容器负责创建Bean, 并将Bean注入到所需的Bean中, 有xml ...
- vue中过滤器比较两个数组取相同值
在vue中需要比较两个数组取相同值 一个大数组一个 小数组,小数组是大数组的一部分取相同ID的不同name值 有两种写法,两个for循环和map写法 const toName = (ids, arr) ...
- redis数据类型(五)set类型
一. set类型 set是无序集合,最大可以包含(2 的 32 次方-1)个元素. set 的是通过 hash table 实现的,所以添加,删除,查找的复杂度都是 O(1). hash table ...
- Android studio--几个生成文件的区别:Make Project、Make Module、Build apk、Signed apk
参考资料: https://stackoverflow.com/questions/35334319/difference-between-make-project-make-module-app-b ...