zoukankan      html  css  js  c++  java
  • Redux学习之我对于其工作流程的理解和实践

    目录

    1 工作流程图

    2 各部位职责

    3 Demo

    1 工作流程图

    2 各部位职责

    我在理解这个流程图的时候,采用的是一种容易记住的办法,并且贴切实际工作职责。
    我们可以把整个Redux工作流程理解成一个图书馆中借书操作。

    • React Components(借书的人)
    • Action Creators (借书的实际操作)
    • Store (图书馆管理员)
    • Reducer (借书记录本)

    因此当我们理解了每个部位的身份后,我们就按照着上面工作流程图一起来屡一下整个过程。首先借书的人(React Component)发起一个借书的实际操作(Action Creators)传达(dispatch)一个(action)给图书馆管理员(Store),图书馆管理员需要查阅借书小本本(Reducer),查阅完以后图书馆就能从借书小本本中获取到返回(return)的信息,再告诉借书的人“OK,我在借书小本本我登记好了,书你可以拿走了”,这样借书的人(React Component)就拿走书了。

    是不是现在有点印象对于整个工作流程?

    3 Demo

    (说了这么多,不练下怎么知道爽不爽呢?)

    3.1 功能介绍

    我们要实现的功能很简单,就是通过redux去管理数据,数据[1, 2, 3]这时候都是从reducer中取出来的。

    3.2 项目中的React Componet

    主要展示两个分别为index.js和todoList.js

    • index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import TodoList from './TodoList';
    
    ReactDOM.render(<TodoList />, document.getElementById('root'));
    

    话不多说!

    • todoList.js
    import React,  { Component } from 'react';
    import 'antd/dist/antd.css';
    import { Input, Button, List } from 'antd';
    import store from './store'; // 等价于 import store from './store/index.js' 
    import { getInputChangeAction, getAddItemAction, getDeleteitemAction } from './store/actionCreator';
    
    class TodoList extends Component {
        
        constructor(props) {
            super(props);
            this.state = store.getState();
            this.handleInputChange = this.handleInputChange.bind(this);
            this.handleStoreChange = this.handleStoreChange.bind(this);
            this.handleBtnClick = this.handleBtnClick.bind(this);
            store.subscribe(this.handleStoreChange); //store中的数据只要被改变,就会自动触发里面的动作
        }
    
        render() {
            return (
                <div style={{marginTop: '10px', marginleft: '10px'}}>  
                    <div>
                        <Input 
                            value={this.state.inputValue} 
                            placeholder='todo info' 
                            style={{ '500px', marginRight: "10px"} } 
                            onChange={this.handleInputChange}
                        >
                        </Input>
                        <Button type="primary" onClick={this.handleBtnClick}>提交</Button>
                    </div>
                    <List
                        style={{marginTop: '10px',  '500px'}}
                        bordered
                        dataSource={ this.state.list }
                        renderItem={ (item, index) => (<List.Item onClick={this.handleItemDelete.bind(this, index)}> {item} </List.Item>) }
                    >    
                    </List>
                
                </div>   
            )
        }
    
        handleInputChange(e) {
            /* 
            原代码,现将action封装到一个独立的actionCreator.js中 便于维护 
            const action = {
                type: CHANGE_INPUT_VALUE,
                value: e.target.value
            }
            */
            const action = getInputChangeAction(e.target.value);
            store.dispatch(action)
        }
    
        handleStoreChange() {
            this.setState(store.getState());
        }
    
        handleBtnClick() {
            const action = getAddItemAction();
            store.dispatch(action);
        }
    
        handleItemDelete(index) {
            const action = getDeleteitemAction(index);
            store.dispatch(action);
        }
    
    }
    
    export default TodoList;
    
    

    简单说两句上述代码。
    1).渲染一个输入框一个按钮,点击按钮,将输入框中的数据发送store中并更改list的值,然后组件会接收到store数据变更将新数据渲染。
    2).点击列表中的每一项会删除该项。其实就是组件发送一个action给store,告诉它,删掉我点的!

    3.3 首先安装redux

        npm install redux --save--dev
    

    3.4 重点开场,创建store文件夹

    store文件总共有四个文件分别如下

    • index.js 在这个文件中创建store
    // index.js
    
    import { createStore } from 'redux';
    import reducer from './reducer';
    
    const store = createStore(
        reducer,
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );  
    
    export default store;
    
    

    简单解释两句以上代码,从redux中引入一个createStore方法,通过这个方法传入我们的小本本reducer,创建一个store。那么问题来了,第二个参数这么一长条是啥玩意?莫慌兄dei~我们为了更好的管理数据通过使用redux去管理,那么chrome有一个Redux Devtools插件可以可视化redux数据。而这一长条就是为了告诉浏览器,听说你有redux可视化数据的插件?还不快给老子显示一下redux数据!

    • actionCreator.js
      还记得它的功能吗?(借书的实际操作!)因此,这个文件中存放的就是我们操作数据时的所有action。
    import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';
    
    export const getInputChangeAction = (value) => ({
        type: CHANGE_INPUT_VALUE,
        value
    });
    
    export const getAddItemAction = () => ({
        type: ADD_TODO_ITEM
    });
    
    export const getDeleteitemAction = (index) => ({
        type: DELETE_TODO_ITEM,
        index
    });
    
    

    1).简单说两句上面的代码,就是导出了三个获得action的方法,因为我们用redux去管理数据的一个目的就是,我们不在把业务逻辑放在React Component中,而是全封装在一个actionCreator中。然后我们就可以在React Componet中直接引入actionCreator,然后吊用其中暴露的接口即可获得一个action,然后再把这个action派发给reducer。

    2).那么再说两句action,在redux中action是一个对象,这个对象中有一个参数是type,记录的就是一个我们需要怎样的操作(换句话说就是这是一个怎样的action),当我们记录了这个type的时候,我们就可以在reducer小本本中根据我们所需要的type从而如何去改变store中的数据;其action这个对象中别的参数可以是我们做这个操作时需要的别的value。

    • actionTypes.js
    // actionTypes.js
    
    export const CHANGE_INPUT_VALUE = 'change_input_value';
    export const ADD_TODO_ITEM = 'add_todo_item';
    export const DELETE_TODO_ITEM = 'delete_todo_item';
    
    

    简单说两句上述代码,这个文件其实是对action中的type进行封装成一个常量。这样做的目的是:如果是一个普通字符串,当我们在一个项目中多次拼写的时候很可能会一个字符没拼对而出bug,而这个bug我们还有可能花一天的时间去找,最后你可能会

    有童鞋可能会说,我都复制还不行吗!行!累不累?但是,既然要用redux去管理数据,我们就一劳永逸吧!

    • reducer.js 、
      说了这么久的小本本,终于到它了!不多说,上代码!
    &emsp;
    //reducer.js
    import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes';
    
    const defaultState = {
        inputValue: '123',
        list: [1, 2, 3]
    };
    
    export default (state = defaultState, action) => {
        // 更改input輸入框的值
        if (action.type === CHANGE_INPUT_VALUE) {
            const newState = JSON.parse(JSON.stringify(state)); //深拷貝
            newState.inputValue = action.value;
            return newState;
        }
        // 将input提交的值插入到数组list中
        if (action.type === ADD_TODO_ITEM) {
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.push(newState.inputValue);
            newState.inputValue = '';
            console.log(newState);
            return newState;
        }
        //刪除item
        if (action.type === DELETE_TODO_ITEM) {
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.splice(action.index, 1);
            return newState;
        }
        return state;
    }
    
    
    

    老规矩,讲代码!
    1.通常我们定义仓库的一个默认值defaultState。
    2.我们导出一个方法。这个方法做的事情就是先记录不同的action.type执行不同的操作,返回给store对应操作后的数据。

    总结:
    当React Component需要执行一个操作时,就会调用actionCreator暴露的接口获得一个action,然后将这个action去dispatch给store,store拿到这样一个action就会去查小本本,然后根据小本本预先设定好的操作执行并返回对应的结果给store,然后store中的数据就会改变。我们通常在React Component的constructor初始化时,执行store.subscribe(this.handleStoreChange)。表示的是,当store数据变化时,就会触发里面的操作拿到最新的数据。

    后续会继续更新
    1.redux-thunk,这个插件使得action除了对象外还可以是一个函数,这样我们可以将一个异步请求,从react组件中封装到store中的actionCreator进行管理。
    2.redux-immutable ,这个插件使得store中的数据成为一个immutable不可变对象
    3.react-redux,连接父子组件的store,使得父组件中引入了store后,如何在子组件中连接并使用这个store

    ----------------作者的话:如果你看到了这里,那说明你真的是一个棒棒哒,第一次发博,码文码字还不是特别专业,不过会慢慢进步的,如有不对的地方,还请大家指点一下!--------------

  • 相关阅读:
    实现连续测试,要做的事情【译】
    Go语言HTTPServer开发的六种实现
    JSON必知必会【PDF+视频教程】
    给JSONObject添加自定义遍历方法
    利用守护线程隐式关闭线程池
    从错误中学习
    Groovy动态添加方法和属性及Spock单测
    持续测试、持续集成、持续交付、持续部署和DevOps
    有关OAuth 2.0简化模式中步骤D-F的解释
    Spring笔记(五):bean的自动装配
  • 原文地址:https://www.cnblogs.com/fe-linjin/p/10457089.html
Copyright © 2011-2022 走看看