本文共 4387 字,大约阅读时间需要 14 分钟。
简单实现了下redux,帮助理解redux的原理:
// 维持应用的 state// 提供 getState() 方法获取 state// 提供 dispatch(action) 方法更新 state// 通过 subscribe(listener) 注册监听器// 通过 subscribe(listener) 返回的函数注销监听器// createStore参数为可变参数,第一个参数为reducer,第二个参数为初始stateexport function createStore(...arg){ let state = null; let reducer = arg[0]; // 使用第二个参数为state初始化 if(arg.length > 1){state = arg[1]} // 保存监听器的数据 let listeners = []; let getState = () => state; let subscribe = listener => listeners.push(listener) let dispatch = (action) =>{ //执行reducer函数,更新状态 state = reducer(state,action) //遍历listeners,执行之中的监听器函数 listeners.forEach(listener => listener()) } return { getState, dispatch, subscribe }}
实现了redux的createStore方法,代码没几行,应该能看懂吧。
// import {createStore} from 'redux'import {createStore} from '../myredux'import reducer from './reducer'const initialState = { counter:0, title:'nihao'}const store = createStore(reducer,initialState)export default store;
把导入redux的代码换成myredux即可,其他使用和redux一样。当然,redux的中间件并没有实现。
react-redux实现思路
let Container = ({store}) => { let [counter,setCounter] = useState(0); useEffect(() =>{ store.subscribe(() => { setCounter(store.getState().counter) }); }) let add = () =>{ store.dispatch({ type:"INCREASE", num:1 }) } let min = () =>{ store.dispatch({ type:"DECREASE", num:1 }) } return}export default ({Consumer}) => ( { (store) => )}
使用
问题是, <Container/>
里面绑定了 <Counter/>
而且还需要把 <Consumer>
通过props传到 <Container/>
里。
并且 展示组件里也只能获取一个状态 counter
实现了 connect
函数,用法和 react-redux
基本一样,代码如下:
connect.js
import React,{createContext} from 'react';const {Provider,Consumer} = createContext();export const Container = ({store,children}) => { return ()}class Inner extends React.Component{ constructor(props){ super(props) this.state = {} let {mapStateToProps,store} = this.props; //从mapStateToProps获得用户需要的状态 let mapState = mapStateToProps(store.getState()); for(let key in mapState){ this.state[key] = mapState[key] } } componentDidMount(){ let {store} = this.props //注册监听,这样当state发生改变时,改变Inner的内部状态,把这个新状态在render中传给了展示组件Comp,Comp就可以实时获取最新状态了 store.subscribe(()=>{ let storeState = store.getState(); for(let key in this.state){ this.setState({ [key]: storeState[key] }) } }) } render() { let {store,Comp,mapDispatchToProps} = this.props; let actions = mapDispatchToProps(store.dispatch) //把状态和方法传入到展示组件中 return ({children} ) }}//connnect是一个高阶组价,返回一个函数,接受展示组件为参数,使用 包装,传入 storeexport const connect = (mapStateToProps,mapDispatchToProps) =>{ return (Comp) => { return () => ( { (store) =>( ) }}) }
使用方法,和 react-redux
基本上是一模一样的,只不过把 Provider
换成了 Container
,不过我完全可以叫 Provider
,一个名称而已。
在App.js:
import React from 'react';import './App.css';import store from './store'import Cart from './components/Cart1'import {Container} from './connect.js'function App() { return ();}export default App;
cart.js
import React from 'react'import {connect} from '../connect'let Counter = ({counter,title,min,add,changeTitle}) =>{ return ()}const mapStateToProps = (state) => { return { counter: state.counter, title:state.title }}const mapDispatchToProps = (dispatch) => { return { add: () => { dispatch({type:"INCREASE",num:1}) }, min: () => { dispatch({type:"DECREASE",num:1}) }, changeTitle() { dispatch({type:"UPDATE_TITLE"}) } }}export default connect(mapStateToProps,mapDispatchToProps)(Counter);{counter}
{ title }
已经可以和 react-redux
完全一样的用法。
当然,这里的实现只是为了帮助理解 react-redux
内部是如何实现,并不一定是最好用的,实际工作中直接使用 react-redux
就好了。
代码放在Github上了,欢迎star:
转载地址:http://pvqni.baihongyu.com/