其实上文的代码中对于 createStore 的实现原理已经基本描述清除,下面我们只是单纯的对代码进行了简单的封装;当然为了能够获取到 state 我们专门增加了一个函数 getState 来实现它;
createStore 函数实现// redux.js export const createStore = (reducer) => { // 声明常量 let state; const listeners = []; // 获取状态 const getState = () => { return state; } // 添加监听对象 const subscribe = (listener) => { listeners.push(listener); } // [1]执行reducer修改状态 [2]遍历执行监听对象 const dispatch = (action) => { state = reducer(state, action); listeners.forEach(v => v()); } // 初始化 state dispatch({type: '%$&HJKAJJHDJHJ'}); // 暴露接口 return {getState, subscribe, dispatch}; }
调用 createStore 并对 demo 进行修改// Demo.jsx import React from 'react'; import './style.css'; import { changeAge, changeUser } from './actionCreate'; import { reducer } from './reducer'; import { createStore } from './redux'; const store = createStore(reducer); export default class Demo extends React.Component{ state = {user: 'xxx', age: 'xxx'}; componentDidMount(){ store.subscribe(this.update); this.update(); } update = () => { this.setState(store.getState()); } onChange = (e) => { store.dispatch(changeUser(e.target.value)); } onClick = () => { store.dispatch(changeAge()); } render(){ return ( <div> <p>user: {this.state.user}, age: {this.state.age}</p> user: <input type="text" className="input" onChange={this.onChange}/> <button className="btn" onClick={this.onClick}>年龄增长</button> </div> ); } }
二、 react-redux API Provider 的实现
在 react 中大多数情况下我们需要将状态传递给后代组件进行使用的,当然通过 props 是可以实现状态从父级到子级的传递,但是当状态需要传递的层级比较深的情况下再使用 props 就显得无力了,那么在 react-redux 中它是如何实现对 store 的传递的呢?
2.1 react context 的引入
在 App.js 中创建 store 并通过 context 传递 store// App.js import React, { Component } from 'react'; import propTypes from 'prop-types'; import { createStore } from './Demo/redux'; import { reducer } from './Demo/reducer'; import Demo from './Demo/Demo'; // 创建 store const store = createStore(reducer); class App extends Component { // 声明 childContextTypes 状态属性类型 static childContextTypes = { store: propTypes.object }; // 设置 childContext getChildContext(){ return {store} } render() { return <Demo />; } } export default App;
在子组件 Demo 中通过 context 获取 store 并对代码进行简单修改// Demo.jsx import React from 'react'; import propTypes from 'prop-types'; import './style.css'; import { changeAge, changeUser } from './actionCreate'; export default class Demo extends React.Component{ // 设置 context 状态值类型 static contextTypes = { store: propTypes.object }; constructor(props, context){ super(props, context); // 获取store this.store = context.store; this.state = {user: 'xxx', age: 'xxx'}; } componentDidMount(){ this.store.subscribe(this.update); this.update(); } update = () => { this.setState(this.store.getState()); } onChange = (e) => { this.store.dispatch(changeUser(e.target.value)); } onClick = () => { this.store.dispatch(changeAge()); } render(){ return ( <div> <p>user: {this.state.user}, age: {this.state.age}</p> user: <input type="text" className="input" onChange={this.onChange}/> <button className="btn" onClick={this.onClick}>年龄增长</button> </div> ); } }
2.2 封装代码实现 Provider
通过 react context 我们实现了对 store 的传递,到这里 Provider 的功能以及实现原理基本上应该算是清晰了,无非就是对组件进行包裹同时通过 react context 来传递共享 store;那么接下来我们通过对代码的封装来实现 Provider 组件;
Provider 组件:实现对 store 的传递