redux的使用和基础原理
-
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> -
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 } } -
redux工程化
- 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- 派发标识的宏管理
// 派发标识统一管理,可在reducer、dispatch方法中引用标识 // 路径:store/action-type.js export const VOTE_SUP = "VOTE_SUP" export const VOTE_OPP = "VOTE_OPP"- 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- 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 } }