简单实现了下redux,帮助理解redux的原理:css
// 维持应用的 state // 提供 getState() 方法获取 state // 提供 dispatch(action) 方法更新 state // 经过 subscribe(listener) 注册监听器 // 经过 subscribe(listener) 返回的函数注销监听器 // createStore参数为可变参数,第一个参数为reducer,第二个参数为初始state export 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方法,代码没几行,应该能看懂吧。react
// 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的中间件并无实现。git
react-redux实现思路
借助于context,把store经过Provider实现共享,这样,在Provider内部的子组件就能够得到store,而后在内部组件,须要获取状态的地方,使用consumer包装,得到store,就能够实现状态共享了。
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 <Counter counter={counter} min={min} add={add}/> } export default ({Consumer}) => ( <Consumer> { (store) => <Container store={store}/>} </Consumer>)
使用github
<Provider store={store}> <Container Consumer={Consumer}> </Container> </Provider>
问题是,<Container/>
里面绑定了<Counter/>
并且还须要把<Consumer>
经过props传到<Container/>
里。
而且 展现组件里也只能获取一个状态counter
redux
实现了connect
函数,用法和 react-redux
基本同样,代码以下:
connect.jside
import React,{createContext} from 'react'; const {Provider,Consumer} = createContext(); export const Container = ({store,children}) => { return ( <div> <Provider value={store}> {children} </Provider> </div> ) } 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 (<Comp {...actions} {...this.state} />) } } //connnect是一个高阶组价,返回一个函数,接受展现组件为参数,使用<Consumer/>包装,传入 store export const connect = (mapStateToProps,mapDispatchToProps) =>{ return (Comp) => { return () => ( <Consumer> { (store) =>( <Inner Comp={Comp} store={store} mapStateToProps={mapStateToProps} mapDispatchToProps={mapDispatchToProps}></Inner> ) } </Consumer>) } }
使用方法,和react-redux
基本上是如出一辙的,只不过把Provider
换成了Container
,不过我彻底能够叫Provider
,一个名称而已。函数
在App.js:this
import React from 'react'; import './App.css'; import store from './store' import Cart from './components/Cart1' import {Container} from './connect.js' function App() { return ( <Container store={store}> <Cart/> </Container> ); } export default App;
cart.jsspa
import React from 'react' import {connect} from '../connect' let Counter = ({counter,title,min,add,changeTitle}) =>{ return ( <div> <h1> {counter} </h1> <h2> { title }</h2> <button onClick={min}> - </button> <button onClick={add}> + </button> <button onClick={changeTitle}> update title </button> </div>) } 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);
已经能够和react-redux
彻底同样的用法。
固然,这里的实现只是为了帮助理解react-redux
内部是如何实现,并不必定是最好用的,实际工做中直接使用 react-redux
就行了。code
代码放在Github上了,欢迎star: https://github.com/cooleye/co...,