关于react.js:redux原理是什么

33次阅读

共计 5210 个字符,预计需要花费 14 分钟才能阅读完成。

前言

置信很多人都在应用 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

React 实战视频解说:进入学习

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 了

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 的原理剖析

正文完
 0