前言
置信很多人都在应用redux作为前端状态治理库进去我的项目开发,但依然停留在“晓得怎么用,但依然不晓得其外围原理”的阶段,接下来带大家剖析一下redux和react-redux两个库的核心思想和API
redux
1.为什么要应用redux?
随着互联网的高速倒退,咱们的利用变得越来越简单,进行导致咱们的组件之间的关系也变得日趋简单,往往须要将状态父组件 -> 子组件 -> 子子组件 -> 又或者只是简略的 父组件与子组件之间的props传递也会导致咱们的数据流变得难以保护,因为二次开发者不在相熟我的项目的状况下无奈第一工夫确定数据起源是由谁发动的。应用redux之后,所有的状态都来自于store中的state,并且store通过react-redux中的Provider组件能够传递到Provider组件下的所有组件,也就是说store中的state对于Provider下的组件来说就是全局的。
2.redux的外围原理是什么?
1.将利用的状态对立放到state中,由store来治理state。
2.reducer的作用是返回一个新的state去更新store中对用的state。
3.按redux的准则,UI层每一次状态的扭转都应通过action去触发,action传入对应的reducer 中,reducer返回一个新的state更新store中寄存的state,这样就实现了一次状态的更新
4.subscribe是为store订阅监听函数,这些订阅后的监听函数是在每一次dipatch发动后顺次执行
5.能够增加中间件对提交的dispatch进行重写
3.redux的api有哪些?
1.createStore 创立仓库,承受reducer作为参数
2.bindActionCreator 绑定store.dispatch和action 的关系
3.combineReducers 合并多个reducers
4.applyMiddleware 洋葱模型的中间件,介于dispatch和action之间,重写dispatch
5.compose 整合多个中间件
接下来咱们来顺次实现createStore、bindActionCreator、combineReducers、applyMiddleware、compose
createStore的实现
function createStore (reducer, enhancer) { if (enhancer) { enhancer(createStore)(reducer) } let currentState = {} //这就是后面提到的store治理的state let currentListener = [] //这是后面提到的为store增加监听函数 function subscribe (func) { currentListener.push(func) } function getState () { return JSON.parse(JSON.stringify(state)); } funtion dispatch (action) { currentState = reducer(currentState, action) currentListener.map(listen => listen()) //每当产生顺次dispatch后都会遍历监听函数并执行 return action } return { subscribe, getState, dispatch }}
留神: createStore并没有间接返回store中寄存的state,而是返回一个函数getState来获取state,当咱们调用getState去获取state时,须要返回一个state的复制品,也就是须要返回一个深拷贝state之后对象,这样能够防止state值的非法篡改,因为如何间接返回state的话,只需通过state[key] = xxxx就能对state进行批改,违反了redux只能通过dispatch(action)去更新state
bindActionCreator的实现
function bindActionCreator (creators, dispatch) { let bound = {} Object.keys(creators).map(key =>{ const creator = creators[key] bound[key] = (..args) => dispach(creator(...args)) }) return bound}
bindActionCreator是为action函数外面包一层dispatch,这样在进行action发动时无需再手动dispatch了,相干React实战视频解说:进入学习
combineReducers的实现
function combineReducers (reducers) { const reducersKeys = Object.keys(reducers), finalReducers = {} for (let i = 0; i < reducerKeys.length; i++) { if (typeof reducers[i] === 'function') { finalReducers[i] = reducers[i] } } const finalReducersKeys = Object.keys(finalReducers) return function combination (state={}, action) { let hasChanged = false, nextState = {} for (let i = 0; i < finalReducersKeys.length; i++) { const key = finalReducersKeys[i], reducer = finalReducers[key], preStateKeys = state[key], nextStateKeys = reducer(preState, action), nextState[key] = nextStateKeys hasChanged = hasChanged || preStateKeys !== nextStateKeys } return hasChanged ? nextState : state }}
applyMiddleware的实现
function applyMiddleware (...middlewares) { return createStore => (...args) => { const store = createStore(...args) let { getState, dispatch } = store const middlewateApi = { getState, dispatch: (...args) => dispatch(...args) } const middlewareChain = middlewares.map(middleware => middlware(middlewareApi)) dispatch = compose(...middlewareChanin)(dispatch) return { store, dispatch } }}
compose的实现
function compose (...funcs) { if(funcs.length === 0) { return args => args } if (funcs.length === 1) { return funcs[0] } return funcs.reduce( (ret, item) => (...args) => ret(item(...args)) )}
compose是整合多个中间件的状况,这里应用reduce对用传入的中间件进行累加执行
react-redux
1.为什么要应用react-redux?
答复这个问题,只须要明确咱们的最终目标:能在react组件中实现对store中的state进行获取、批改、监听,而从上述内容能够晓得,createStore会给咱们返回getState、dispatch、subscribe来进行获取state、批改state、监听state变动,而咱们当初要做的就是把这个三个函数传递给react组件就能够了,所以咱们就须要react-redux来帮忙咱们
2.react-redux的外围原理是什么?
1.将Provider高阶组件包裹在组件的最外层,并且将创立的store传入Provider高阶组件中,
而后再Provider高阶组件外部获取传入的store并将它增加到Provider高阶组件的context上下文中,context是react组件特有的一种不必手动一层层传递props就能在组件树中传递数据的形式,这样就实现了store绝对于react组件的全局化,所有组件都能对store进行批改,获取,监听了
2.尽管Provider下的组件都领有能够操作store的能力了,然而因为假使咱们要在每一个组件都从context中去获取store会造成大量代码冗余,还有一点就是即便你能在react组件中可能操作store了,然而当你dispatch一个action之后,store中的state尽管更新了,然而并不会触发组件中的render函数去渲染新的数据,所以咱们就须要通过react-redux另一个高阶组件connect
来做集中处理。connect组件承受一个component组件返回一个新的component组件,在connect最终返回的组件中获取store并将store设置为以后组件的state,并且在connect返回的组件中的componentDidMount周期函数中调用subscribe给store绑定监听函数,而这个监听函数就是负责以后store中的state产生扭转时,通过this.setState来触发组件的render函数的调用,最终达到store中的state与UI中state同步的问题
3.react-redux有哪些API?
1.Provider组件通过context的形式将store注入利用
2.Connect高阶组件,获取并监听store,而后依据store state和组件本身props计算失去新props,注入该组件,并且能够通过监听store,比拟计算出的新props判断是否须要更新组件
Provider的实现
import React, { Component } from 'react'import PropTypes from 'prop-types'class Provider extends Component { constructor (props) { super(props) this.store = props.store } static propTypes = { store: PropTypes.object } getChildContext () { return { store: this.store } } render () { return this.props.children }}
若存在疑问请回顾下面react-redux的原理剖析
connect的实现
import React, { Component } from 'react'import PropTyeps from 'prop-types'import { bindActionCreator } from 'redux'const connect = (mapStateToProps, dispatchStateToProps) => (WrapperComponent) => class Connect extends Component { construtor (props, context) { super(props, context) this.store = context.store this.state = { props: {} } } static contextTypes = { store: PropTypes.object } componentDidMount () { this.store.subscribe(this.update) this.update() } update = () => { const { getState, dispatch } = this.store const stateProps = mapStateToProps(getState()) const dispatchProps = bindActionCreator(dispatchStateToProps, dispatch) this.setState({ ...this.state.props, ...stateProps, ...dispatchProps, }) } render () { const { props } = this.state return <WrapperComponent {...props} /> }}
若存在疑问请回顾下面react-redux的原理剖析