redux使用与工程化、部分源代码

50 阅读2分钟

redux的使用和基础原理

  1. redux的使用

    // 1.创建store
    // 路径:store/index.js
    import {createStore} from 'redux'
    import reducer from './reducer'
    
    const stroe = createStore(reducer)
    export default store
    
    
    // 2.创建reducer
    // 路径:store/reducer
    const initial = {
        supNum: 10,
        oppNum: 5,
    }
    const reducer = (state = initial, action) => {
        state = {...state}
        switch(action.type) {
            case 'VOTE_SUP':
                state.supNum++
                break;
            default:
        }
        return state
    }
    export default reducer
    
    
    // 3.创建上下文
    // 路径: ThemeContext
    import react from 'react'
    
    const ThemeContext = React.createContext()
    export ThemeContext
    
    
    // 4.在组件中使用
    // 路径: index.jsx
    import ThemeContext from './ThemeContext'
    import store from './store'
    import Vote from './views/Vote'
    
    // 将store放入上下文中
    <ThemeContext.Provider
        value = {{
            store
        }}
    >
        <Vote />
    </ThemeContext.Provider>
    
    // 函数组件Vote
    // 路径 views/Vote.jsx
    import ThemeContext from './ThemeContext'
    import {useContext, useState, useEffect} from 'react'
    
    const {store} = useContext(ThemeContext) // 从上下文中获取store
    const {supNum} = store.getState() // 通过store.getState()方法获取数据
    const [_, setNum] = useState(0)
    useEffect(() => {
        let unsubscribe = store.subscribe(() => {
            setNum(+new Date())
        }) // 通过store.subscribe()将组件更新事件放入事件池中
        return () => {
            unsubscribe() // 释放事件池中事件
        }
    }, [])
    // 通过dispatch()派发任务
    renturn <>
        <div onClick={store.dispatch.bind(null, {type: 'VOTE_SUP'})}>
            {supNum}
        </div>
    </>
    
    // 类组件Vote
    // 路径 views/Vote.jsx
    import ThemeContext from './ThemeContext'
    
    static contextType = ThemeContext
    render() {
        const {store} = this.context // 从上下文中获取store
        const {supNum} = store.getState() // 通过store.getState()方法获取数据
        // 通过dispatch()派发任务
        return <>
            <div onClick={store.dispatch.bind(null, {type: 'VOTE_SUP'})}>
                {supNum}
            </div>
        </>
    }
    componentDidMount() {
        const {store} = this.context
        // 通过store.subscribe()将组件更新事件放入事件池中
        store.subscribe(() => {
            this.forceUpdate()
        })
    }
    
    
    // 函数组件与类组件通用方法
    import ThemeContext from './ThemeContext'
    
    return <ThemeContext.consumer>
        {
            store => {
                const {supNum} = store.getState()
                return <div>
                    {supNum}
                </div>
            }
        }
    <ThemeContext.consumer>
    
  2. redux源码

    // myredux.js
    // store存储state状态与事件池,通过getState方法获取state,通过subscribe方法向事件池添加方法,通过dispatch派发任务获取最新state并更新组件
    
    const myredux = (reducer) => {
        // 校验reducer是否函数
        
        let state, // 状态
            listeners = [] // 事件池
        
        // 获取状态
        const getState = () => {
            return state
        }
        
        // 添加事件池
        const subscribe = (listener) => {
            // 校验listener是否函数
            
            // 添加到事件池
            if (!listeners.includes(listener)) {
                listeners.push(listener)
            }
            return () => {
                const index = listeners.indexOf(listener)
                listeners.splice(index, 1)
            }
        }
        
        // 派发任务
        const dispatch = (action) => {
            // 校验action是否对象,是否包含type属性
            
            // 执行
            state = reducer(state, action)
            listeners.forEach(listener => listener())
            return action
        }
        
        // redux内部会默认执行一次dispatch
        const randomString = Math.random().toString(36).substring(7).split('').join('.')
        dispatch({
            type: '@@redux/INIT' + randomString()
        })
        
        return {
            getState,
            subscribe,
            dispatch
        }
    }
    
  3. redux工程化

    1. reducer的拆分合并
    // reducers合并
    // 路径:store/reducers/index.js
    import { combineReducers } from 'redux'
    import voteReducers from './voteReducers'
    import personalReducers from './voteReducers'
    
    const reducers = combineReducers({
        vote: voteReducers,
        personal: personalReducers
    })
    export default reducers
    
    // 子reducers
    // 路径:store/reducers/voteReducers.js
    const initial = {
        supNum: 10,
        oppNum: 5,
    }
    const voteReducer = (state = initial, action) => {
        state = {...state}
        switch(action.type) {
            case 'VOTE_SUP':
                state.supNum++
                break;
            default:
        }
        return state
    }
    export default voteReducer
    
    1. 派发标识的宏管理
    // 派发标识统一管理,可在reducer、dispatch方法中引用标识
    // 路径:store/action-type.js
    
    export const VOTE_SUP = "VOTE_SUP"
    export const VOTE_OPP = "VOTE_OPP"
    
    1. actionCreator的创建
    // 把派发对象,按照模块统一管理
    // sotre/action/index.js
    import voteAction from './voteAction'
    import personalAction from './personalAction'
    
    const action = {
        vote: voteAction,
        personal: personalAction
    }
    export default action
    
    
    // 子aciton
    // 路径:store/action/voteAction.js
    import * as TYPES from '../action-type'
    const voteAction = {
        support() {
            return {
                type: TYPES.VOTE_SUP
            }
        }
        oppose() {
            return {
                type: TYPES.VOTE_OPP
            }
        }
    }
    export default voteAction
    
    1. combineReducers源代码
    // combineReducers方法可传入多个reducers,并返回一个函数
    
    const combineReducers = (reducers) => {
        const reducersKeys = Reflect.owenKeys(reducers)
            
        return function reducer(state = {}, action) {
            let nextState = {}
            // 遍历执行每个reducer,传入state和aciton
            reducersKeys.forEach(key => {
                const reducer = reducers[key] 
                nextState[key] = reducer(state[key], action)
            })
            // 返回状态值给store
            return nextState
        }
    }