React进阶(4)-拆分Redux-将store,Reducer,action,actionTypes独立管理

前言

在前面的几小节中已经完成了一个todolist的添加,删除的操做,经过把组件的数据放到了Redux中的公共存储区域store中去存储,在Redux中进行状态数据的更新修改css

改变store的数据惟一办法就是派发action,调用store.dispatch方法,也知道经过getState方法获取store中的全部状态数据,而实现组件页面的更新与store保持同步,必须得触发注册subscribe方法,通时还得监听一个事件处理函数html

用于从新在一次获取store的数据使页面同步更新react

在上几回编写Redux的代码中,建立store,reducer,acton,以及actionTypes(动做类型)都是放在一个文件当中进行编写的,然而更改store可能有多个action动做,全部代码杂糅在一块儿,后期维护起来显然是很是痛苦的git

因此有必要进行将Redux代码进行按照特定的职责,功能结构进行拆分的,其实也就是把以前各个逻辑代码拆分到各个文件当中去单独管理的 编程

Redux(4)-拆分Redux.jpg

完整的TodoList代码

这是上一节完整的一todolist的代码,建立store,reducer,以及action,UI组件等都是混写在一个文件当中的,这样虽然没有什么问题,可是维护起来,很是痛苦,若是一个文件里代码行数超过了130行,就应该考虑拆分代码了的,固然这并非硬性的规定,适当的拆分有利于代码的维护,可是过分的拆分,也会增长项目的复杂程度json

import React from 'react';
import ReactDOM from 'react-dom';
import { Input, Button, List, message, Modal } from 'antd'; // 引入antd组件库
import 'antd/dist/antd.css'; // 引入antd样式


// 1. 建立一个store管理仓库,从redux库中引入一个createStore函数
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';

// 2. 引入createStore后,store并无建立,须要调用createStore()后才有store
//const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); // 建立好reducer后,须要将reducer做为参数传到createStore当中去,这样store才能拿到reducer的state数据
const store = createStore(reducer, composeWithDevTools(applyMiddleware())); // 建立好reducer后,须要将reducer做为参数传到createStore当中去,这样store才能拿到reducer的state数据

// 3. 建立reducer函数,管理组件共享的数据状态以及一些动做
// reducer是一个纯函数,返回一个新的state给store
// 4. 初始化state值,将原先组件内部的状态的数据,移除到reducer里面去管理
function reducer(state = {
    inputValue: '',
    list: []
}, action) {
    console.log(state, action);
    if (action.type === 'handle_Input_Change') {
        // 对原有的上一次的state作一次深拷贝,在Redux中,reducer不容许直接修改state
        // const newState = Object.assign({}, state);
        const newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value; // 将新的value值赋值给newState
        return newState;
    }
    if (action.type === 'addInputcontent') {
        const newState = JSON.parse(JSON.stringify(state));
        if (Trim(newState.inputValue) === '') {
            message.error('输入表单内不能为空,请输入内容');
        } else {
            newState.list.push(newState.inputValue); // 往list数组中添加input的内容
            newState.inputValue = '';
            return newState; // 返回newState
        }

    }
    if (action.type === 'deletelist') {
        // 下面这个也是拷贝原对象的一种方式与上面等价
        const newState = Object.assign({}, state);
        newState.list.splice(action.index, 1);
        return newState;
    }
    return state;
}

// 去除先后空格
function Trim(str) {
    return str.replace(/(^\s*)|(\s*$)/g, "");
}
const { confirm } = Modal
// TodoList组件
class TodoList extends React.Component {

    constructor(props) {
        super(props);
        // 5. 在组件内部经过getState()方法就能够拿到store里面的数据
        this.state = store.getState();
        // this环境的绑定
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleAddClick = this.handleAddClick.bind(this);
        // 触发订阅,让store感知到state的变化
        store.subscribe(this.handleStoreChange); // 接收一个函数,从新获取store最新的数据,subscribe里面必须接收一个函数,不然是会报错的,这个订阅函数放在componentWillMount生命周期函数内调用操做也是能够的
    }
    // componentWillMount(){
    // store.subscribe(this.handleStoreChange); 
    // }
    // 组件卸载,移除时调用该函数,通常取消,清理已注册的订阅,定时器的清理,取消网络请求,在这里面操做
    componentWillUnmount() {
        store.unsubscribe(this.handleStoreChange);
    }

    render() {
        return (
            <div style={{width:'600px',margin: "100px auto"}}>
                    <div>
                        <Input onChange={this.handleInputChange} value={this.state.inputValue} style={{ width:"300px",marginRight:"10px"}}  placeholder="请输入内容..." />
                        <Button type="primary" onClick={this.handleAddClick}>提交</Button>
                    </div>
                    <List
                      style={{ width: '300px',marginTop:'10px'}}
                      bordered
                      dataSource={this.state.list}
                      renderItem={(item,index) => <List.Item onClick={this.handleDelList.bind(this, index,item)}>{item}</List.Item>}/>
            </div>
        )
    }

    handleInputChange(e) {
        console.log(e.target.value);
        // 定义action,肯定一个操做,动做,注意action必须遵循必定的规范,是一个对象,type字段是肯定要作的动做,类型,监听表单输入框的变化,value是输入框的值
        const action = {
            type: 'handle_Input_Change',
            value: e.target.value
        }
        store.dispatch(action); // 经过store派发dispatch一个action,只有这里接收一个action,Reducer里面才能对新旧数据进行计算等操做

    }

    handleStoreChange() {
        console.log("handleStorechange,触发了");
        this.setState(store.getState()); // 触发setState从新获取store的数据,让input的数据与store保持同步了的
    }

    // 添加列表的操做
    handleAddClick() {
        console.log("添加按钮执行了");
        // 定义action动做
        const action = {
            type: 'addInputcontent'
        }
        store.dispatch(action); // 还要将action传递给dispatch,这样store才会接收到
    }

    // 删除列表操做
    handleDelList(index,item) {
        this.showDeleteConfirm(index, item);
    }

    showDeleteConfirm(index,item) {
        const action = {
            type: 'deletelist',
            index: index
        }
        confirm({
            title: '肯定要删除该列表?',
            content: item,
            okText: '确认',
            okType: 'danger',
            cancelText: '取消',
            onOk() {
                console.log('OK');
                 store.dispatch(action);
            },
            onCancel() {
                console.log('Cancel');
            },
        });
    }
}
const container = document.getElementById('root');

ReactDOM.render(<TodoList />, container);
复制代码

此时,项目的src根目下只有一个index.js文件,项目的目录树结构是这样的redux

D:\公开课\2019\React进阶\lesson2
├─split-redux
|      ├─.gitignore
|      ├─package-lock.json
|      ├─package.json
|      ├─README.md
|      ├─yarn-error.log
|      ├─yarn.lock
|      ├─src
|      | ├─index.js
|      ├─public
|      |   ├─favicon.ico
|      |   ├─index.html
|      |   └manifest.json
复制代码

下面来一步一步拆分的,先从简单的入手,不断的简化代码的数组

拆分ActionTypes定义成一个常量,独立管理

改变store里面state数据,惟一的办法就是派发action,调用store.dispatch(action)方法bash

而定义action,它得是一个对象,该对象下type类型必须是一个字符串类型值,这个类型值必须和reducer里面action.type后面的值相同,若是不相等,控制台虽然不报错,可是却会影响实际的功能网络

代码以下所示

// 定义action,也就是具体要作的什么事情
const action = {
      type: 'handle_Input_Change', // 这个type后面的字符串值与在reducer里面的action.type相同
      value: e.target.value
}
// 字符串类型值要与reducer相同
function reducer(state, action){
    if (action.type === 'handle_Input_Change') { // 这个必需要与上面定义相同
        // 对原有的上一次的state作一次深拷贝,在Redux中,reducer不容许直接修改state
        // const newState = Object.assign({}, state);
        const newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value; // 将新的value值赋值给newState
        return newState;
    }
}
复制代码

在根目录src下建立一个store文件夹,而后在新建一个actionsTypes.js

把上面action对象下的type的类型值定义成一个常量,而后对外暴露出去,由于这个动做type类型每每是固定的,通常不怎么去改变,类型值与常量名都定义成同名,这里的类型值与常量名设置成同名不必定非要一致,可是这已是你们约定俗成的一种规定,是个良好的开发习惯

定义actionType类型以下所示,将action的type类型值定义成常量

const CHANGE_INPUT_VALUE = 'CHANGE_INPUT_VALUE';

export {
	CHANGE_INPUT_VALUE
}
复制代码

而后在须要使用actionType类型处,引入该暴露的变量对象便可

import { CHANGE_INPUT_VALUE } from './store/actionTypes'; // 引入actionTypes类型

handleInputChange(e) {
        const action = {
            type: CHANGE_INPUT_VALUE,  // 这里引入上面定义的变量对象
            value: e.target.value
        }
        store.dispatch(action); // 经过store派发dispatch一个action,只有这里接收一个action,Reducer里面才能对新旧数据进行计算等操做

    }

复制代码

以此类推,按照以上模式把action里面的type类型值都更改为常量,放到一个文件(actionTypes.js)去管理的,这个文件只用于定义动做action类型的常量

由于上面的代码中的action有三个:因此完整的以下所示:

const CHANGE_INPUT_VALUE = 'CHANGE_INPUT_VALUE';  // 监听input框输入值的常量
const ADD_INPUT_CONTENT = 'ADD_INPUT_CONTENT';    // 添加列表
const DELETE_LIST = 'DELETE_LIST';                // 删除列表


export {
	CHANGE_INPUT_VALUE,
	ADD_INPUT_CONTENT,
	DELETE_LIST
}
复制代码

而后在须要使用action Type的地方引用便可

import { CHANGE_INPUT_VALUE, ADD_INPUT_CONTENT, DELETE_LIST } from './store/actionTypes'; // 引入actionTypes

// 监听input变化动做
handleInputChange(e) {
        const action = {
            type: CHANGE_INPUT_VALUE,
            value: e.target.value
        }
        store.dispatch(action);

}

// 添加列表的操做
handleAddClick() {
    // 定义action动做
    const action = {
        type: ADD_INPUT_CONTENT
    }
    store.dispatch(action); // 还要将action传递给dispatch,这样store才会接收到
}

// 删除列表操做
    handleDelList(index,item) {
        this.showDeleteConfirm(index, item);
    }

    showDeleteConfirm(index,item) {
        const action = {         // action在这里
            type: DELETE_LIST,   
            index: index
        }
        confirm({
            title: '肯定要删除该列表?',
            content: item,
            okText: '确认',
            okType: 'danger',
            cancelText: '取消',
            onOk() {
                console.log('OK');
                 store.dispatch(action);
            },
            onCancel() {
                console.log('Cancel');
            },
        });
    }
复制代码

通过上面的处理,关于action的type类型值就已经拆分出去了的,至于拆分action中type类型值的好处就是,当你由于不当心把actionType拼写错误时,它会有很好的错误异常提示,这就是定义成一个常量的好处

拆分action,将它封装到一个函数里面去管理

在上面的代码中,只是把action中的type类型值定义成一个常量而后拆分了出去的,可是仍然发现,代码并无简化多少,其实在派发action以前,改变store的数据,对于action的动做(具体要作的事情),是不该该直接定义在咱们的组件里,在事件处理函数里面定义action对象不是不能够

可是这样代码的内聚性不高,对于简易的项目,一些action定义在各个组件内,也没有什么,可是一多的话,找起来就是灾难了的,不利于后续代码的维护,若是你可以把相应的action代码拆分出去,后来的同窗必定会感谢你的,固然随之而然就是增长了点阅读代码的复杂度

若是是高手,那绝对从心里上是要感谢那种把action拆分到一个文件里去管理的,至于初学者,那确定以为特么复杂的,很是绕以及难以理解的,其实只要把Redux的工做流程图理清楚了,也就天然为何要这么拆分了的

一般来讲,咱们把上面的action都放在一个action Creators.js的文件中去管理的,管理这个action文件代码的名字并非固定的,你想要怎么定义成管理action的任何一个名字均可以,可是最好是见名知意

具体actionCreators.js代码以下所示:

import { CHANGE_INPUT_VALUE, ADD_INPUT_CONTENT, DELETE_LIST } from './actionTypes'; // 引入actionTypes

// 将action封装成一个函数,用于返回type类型和须要的参数
function getInputChangeAction(value){
	return {
		type: CHANGE_INPUT_VALUE,
		value:value
	}
}

// 获取input框内容,添加列表action函数
function getAddInputContentAction(){
	return {
		type: ADD_INPUT_CONTENT
	}
}

// 获取删除列表acton函数
function getDeleteListAction(index){
	return {
		type: DELETE_LIST,
		index:index
	}
}

// 上面的也等价于,在Es6中有简写函数的形式,与下面是等价的,在React代码中这种写法很常见
/*
const getInputChangeAction = (value) => ({
	type: CHANGE_INPUT_VALUE,
	value
});

const getAddInputContentAction = () => ({ 
	type: ADD_INPUT_CONTENT
})

const getDeleteListAction = index => ({  // 当只有一个参数时,圆括号能够省略,当返回值有多个时,外面须要用一个大括号包裹起来的
	type: DELETE_LIST,
	index
})

*/
// 将变量对象的函数给暴露出去
export {
	getInputChangeAction,
	getAddInputContentAction,
	getDeleteListAction
}

复制代码

在组件所须要引入actionCreactors的地方,引入actions,以下所示:

import { getInputChangeAction, getAddInputContentAction, getDeleteListAction} from './store/actionCreators';


// 监听input操做
 handleInputChange(e) {
        const action = getInputChangeAction(e.target.value);
        store.dispatch(action); 
 }
 
 // 添加操做
 handleAddClick() {
    const action = getAddInputContentAction();
    store.dispatch(action);
 }
 
 // 删除列表操做
    handleDelList(index,item) {
        this.showDeleteConfirm(index, item);
    }

    showDeleteConfirm(index,item) {
        const action = getDeleteListAction(index);
        confirm({
            title: '肯定要删除该列表?',
            content: item,
            okText: '确认',
            okType: 'danger',
            cancelText: '取消',
            onOk() {
                console.log('OK');
                 store.dispatch(action);
            },
            onCancel() {
                console.log('Cancel');
            },
        });
    }

复制代码

通过上面的action的拆分,如今看来咱们的代码清晰多了,经过actionCreators来建立action,这是一个很是好的编程习惯,固然若是过分的拆分,就不免会让人以为项目复杂,在各个文件之间来回切来切去的,若是不清晰他们之间的关系,那么的确是比较绕,可是不能由于这样,就不作拆分的

从长远来看,拆分action是颇有必要的,一是将事件动做的类型定义成常量给分离出去,二是把总体action单独封装成一个函数放在一个单独的文件中进行管理的,它返回对应的类型和必要的参数的

拆分的目的主要是提升代码的可维护性

建立store单独管理

在上面的代码中,已经解决了Redux工做流程中的右半边部分,也就是作了action的拆分管理,那么接下来是整理store和reducer以及React Component了

在store文件夹中建立一个index.js的文件

这个index.js主要用于建立store

import { createStore } from "redux";
// 建立store,调用createStore函数
const store = createStore();


复制代码

建立reducer,更新state数据操做

在store文件夹下建立reducer.js文件,主要用于更新state数据操做,以下代码所示

import { message } from 'antd';
import { CHANGE_INPUT_VALUE, ADD_INPUT_CONTENT, DELETE_LIST } from './actionTypes';
const defaultStatus = {         // 默认初始值
	inputValue: 'itclanCoder',
	list: ['川川','111', '222']
}
function reducer(state=defaultStatus, action){
    if(action.type === CHANGE_INPUT_VALUE){
    	const newState = JSON.parse(JSON.stringify(state));
    	newState.inputValue = action.value;
    	return newState;
    }

    if(action.type === ADD_INPUT_CONTENT){
    	const newState = JSON.parse(JSON.stringify(state));
        if (Trim(newState.inputValue) === '') {
            message.error('输入表单内不能为空,请输入内容');
        } else {
            newState.list.push(newState.inputValue); // 往list数组中添加input的内容
            newState.inputValue = '';
            return newState; // 返回newState
        }
    }

    if(action.type === DELETE_LIST){
    	const newState =  JSON.parse(JSON.stringify(state));
    	newState.list.splice(action.index, 1);
    	return newState;
    }
	return state;
}


// 去除先后空格
function Trim(str) {
    return str.replace(/(^\s*)|(\s*$)/g, "");
}

export default reducer;
复制代码

在建立好reducer后,必定把reducer放到createStore()函数当作参数给传进去,这样store才会真正存储reducer的数据,同时把store给暴露出去,以下store文件夹中index.js的代码

import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from 'redux-devtools-extension'; // 这个是redux-devtools调试工具
import reducer from './reducer';  // 引入reducer
// 建立store
const store = createStore(reducer, composeWithDevTools(applyMiddleware()));

export default store;   // 导出store
复制代码

最后在主入口文件index.js中引入store,全局进行使用的,以下代码所示

import React from 'react';
import ReactDOM from 'react-dom';
import { Input, Button, List, Modal } from 'antd'; // 引入antd组件库
import 'antd/dist/antd.css'; // 引入antd样式
import { getInputChangeAction, getAddInputContentAction, getDeleteListAction} from './store/actionCreators';
import store from './store/';  // 引入store


const { confirm } = Modal
// TodoList组件
class TodoList extends React.Component {

    constructor(props) {
        super(props);
        // 5. 在组件内部经过getState()方法就能够拿到store里面的数据
        this.state = store.getState();
        // this环境的绑定
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleAddClick = this.handleAddClick.bind(this);
        // 触发订阅,让store感知到state的变化
        store.subscribe(this.handleStoreChange); // 接收一个函数,从新获取store最新的数据,subscribe里面必须接收一个函数,不然是会报错的,这个订阅函数放在componentWillMount生命周期函数内调用操做也是能够的
    }
    // componentWillMount(){
    // store.subscribe(this.handleStoreChange); 
    // }
    // 组件卸载,移除时调用该函数,通常取消,清理已注册的订阅,定时器的清理,取消网络请求,在这里面操做
    componentWillUnmount() {
        store.unsubscribe(this.handleStoreChange);
    }

    render() {
        return (
            <div style={{width:'600px',margin: "100px auto"}}>
                    <div>
                        <Input onChange={this.handleInputChange} value={this.state.inputValue} style={{ width:"300px",marginRight:"10px"}}  placeholder="请输入内容..." />
                        <Button type="primary" onClick={this.handleAddClick}>提交</Button>
                    </div>
                    <List
                      style={{ width: '300px',marginTop:'10px'}}
                      bordered
                      dataSource={this.state.list}
                      renderItem={(item,index) => <List.Item onClick={this.handleDelList.bind(this, index,item)}>{item}</List.Item>}/>
            </div>
        )
    }

    handleInputChange(e) {
        const action = getInputChangeAction(e.target.value);
        store.dispatch(action); 
    }

    handleStoreChange() {
        console.log("handleStorechange,触发了");
        this.setState(store.getState()); // 触发setState从新获取store的数据,让input的数据与store保持同步了的
    }

    // 添加列表的操做
    handleAddClick() {
        const action = getAddInputContentAction();
        store.dispatch(action);
    }

    // 删除列表操做
    handleDelList(index,item) {
        this.showDeleteConfirm(index, item);
    }

    showDeleteConfirm(index,item) {
        const action = getDeleteListAction(index);
        confirm({
            title: '肯定要删除该列表?',
            content: item,
            okText: '确认',
            okType: 'danger',
            cancelText: '取消',
            onOk() {
                console.log('OK');
                 store.dispatch(action);
            },
            onCancel() {
                console.log('Cancel');
            },
        });
    }
}
const container = document.getElementById('root');

ReactDOM.render(<TodoList />, container);
复制代码

上面的代码是渲染一个todolist组件的功能,显然对于主入口文件,咱们仍但愿它是比较干净的

咱们继续将todolist组件单独的抽离出去的

抽离容器组件

对于todolist就是一个简单的组件,那么咱们能够把它抽离出去单独定义的,在根目录src下建立一个views文件夹,这个文件夹能够放咱们的视图组件,在里面建一个TodoList.js的文件的 具体代码以下所示:

对于下面用类class定义声明的TodoList组件,称做为一个容器组件,之因此这么叫,是由于在这个组件里面包含不少业务逻辑,例如:this坏境的绑定,生命周期函数,以及一些事件处理函数等,负责整个业务功能组件的逻辑实现,也有人叫它聪明组件的,这个只是个称呼而已,没有褒贬之义 以下代码所示

import React from 'react';
import { Input, Button, List, Modal } from 'antd'; // 引入antd组件库
import 'antd/dist/antd.css'; // 引入antd样式
import { getInputChangeAction, getAddInputContentAction, getDeleteListAction} from '../store/actionCreators';
import store from '../store/index';  // 引入store


const { confirm } = Modal
// TodoList组件
class TodoList extends React.Component {

    constructor(props) {
        super(props);
        // 5. 在组件内部经过getState()方法就能够拿到store里面的数据
        this.state = store.getState();
        // this环境的绑定
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleAddClick = this.handleAddClick.bind(this);
        // 触发订阅,让store感知到state的变化
        store.subscribe(this.handleStoreChange); // 接收一个函数,从新获取store最新的数据,subscribe里面必须接收一个函数,不然是会报错的,这个订阅函数放在componentWillMount生命周期函数内调用操做也是能够的
    }
    // componentWillMount(){
    // store.subscribe(this.handleStoreChange); 
    // }
    // 组件卸载,移除时调用该函数,通常取消,清理已注册的订阅,定时器的清理,取消网络请求,在这里面操做
    componentWillUnmount() {
        store.unsubscribe(this.handleStoreChange);
    }

    render() {
        return (
            <div style={{width:'600px',margin: "100px auto"}}>
                    <div>
                        <Input onChange={this.handleInputChange} value={this.state.inputValue} style={{ width:"300px",marginRight:"10px"}}  placeholder="请输入内容..." />
                        <Button type="primary" onClick={this.handleAddClick}>提交</Button>
                    </div>
                    <List
                      style={{ width: '300px',marginTop:'10px'}}
                      bordered
                      dataSource={this.state.list}
                      renderItem={(item,index) => <List.Item onClick={this.handleDelList.bind(this, index,item)}>{item}</List.Item>}/>
            </div>
        )
    }

    handleInputChange(e) {
        const action = getInputChangeAction(e.target.value);
        store.dispatch(action); 
    }

    handleStoreChange() {
        console.log("handleStorechange,触发了");
        this.setState(store.getState()); // 触发setState从新获取store的数据,让input的数据与store保持同步了的
    }

    // 添加列表的操做
    handleAddClick() {
        const action = getAddInputContentAction();
        store.dispatch(action);
    }

    // 删除列表操做
    handleDelList(index,item) {
        this.showDeleteConfirm(index, item);
    }

    showDeleteConfirm(index,item) {
        const action = getDeleteListAction(index);
        confirm({
            title: '肯定要删除该列表?',
            content: item,
            okText: '确认',
            okType: 'danger',
            cancelText: '取消',
            onOk() {
                console.log('OK');
                 store.dispatch(action);
            },
            onCancel() {
                console.log('Cancel');
            },
        });
    }
}

export default TodoList;

复制代码

其实没有作多大的代码改变,只是把原先的代码挪到另外一个文件管理了的,那么如今的项目目录结构是这样的

D:\公开课\2019\React进阶\lesson2
├─split-redux
|      ├─.gitignore
|      ├─package-lock.json
|      ├─package.json
|      ├─README.md
|      ├─yarn-error.log
|      ├─yarn.lock
|      ├─src
|      |  ├─index.js          // 主入口文件
|      |  ├─views       
|      |  |   └TodoList.js     // 容器组件
|      |  ├─store               // 组件的数据
|      |  |   ├─actionCreators.js     // action建立者
|      |  |   ├─actionTypes.js        // actionType的类型,定义成的常量
|      |  |   ├─index.js                 // 建立的store主文件
|      |  |   └reducer.js                // 建立的reducer       
|      ├─public
|      |   ├─favicon.ico
|      |   ├─index.html
|      |   └manifest.json
复制代码

从这个目录树中,很是清楚了的,由起初在index.js的代码,把redux中的store,reducer,action逐渐剥离出去单独管理了的

总结

本小节主要是对上一节代码的拆分,将Redux中的store,action,以及reducer分离开来,各自独立的管理,职责分明,若是项目比较简单,一开始是能够写在一块的,而后一点一旦的拆分出去的

若是不是老司机,一开始一上来就拆分,若是对Redux的工做流程不是很清晰,不免会有所懵逼的,发现,写着,写着,找不到头绪,不知道本身在写些什么的

在实际开发当中,至于拆分的顺序,不必定按照我这种方式的,合适的流程应当时,先建立store,而后在建立reducer,肯定要作什么事情,编写action,拆分action代码,其中获取store就用getState方法,而更改store就要经过dispatch派发action,这个流程是固定的

固然这个代码仍然优化的地方,咱们在后续当中,仍会进一步的拆分的

相关文章
相关标签/搜索