• 【React自制全家桶】九、Redux入手


    一、React项目中为什么要用Redux

      上图:

    左图当使用纯React开发稍微大点的项目,因为React数据是瀑布式的,只能通过父子组件传递数据,所以实现关系不大的两React的组件之间的数据传递就会让你非常难受,操作起来非常复杂。如右图,由此应运而生了Redux数据流框架,专门解决数据流问题,

    Redux的基本原理就是React的所有组件涉及到的数据全部都存储在共用的Store中,这样所有组件都可以通过Store来改动数据和获取数据,非常方便。

    二、Redux安装

    在已经安装yarn的前提下

    yarn add redux
    

      

    三、Redux工作流讲解

    先上图:

    为了方便理解,我将一个redux的操作流程视为从图书馆取书的流程:

    1、React Components(借书人)

    2、说借一本《React全栈》书(Action Creations就是代表需要进行的操作)

    3、Store(图书馆管理员)听到了这句话

    4、从reducers(记书本)中查询书在哪放着

    5、Store(图书馆管理员)查到(即reducers返回newState)

    6、Store(图书馆管理员)将书交给React Components(借书人)(即:将改动后的state发给React Components(借书人))

    四、Redux使用入门

    1、使用谷歌浏览器下载浏览器rudux插件(建议开启科学上网后下载安装)

    2、在src目录下创建store文件夹

    3、在store文件夹下创建index.js文件作为redux的入口文件

    import {createStore} from 'redux';
    // 引入reducer
    import reducer from './reducer';
    
    const store = createStore(
        reducer,
        // 显示redux调试工具
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    
    export default store;
    

      

    4、在store文件夹下创建reducer.js文件作为数据

    import {CHANGE_INPUT_VALUE , ADD_TODO_ITEM , DELETE_TODO_ITEM} from './actionTypes';
    
    const defaultState = {
        inputValue : "",
        list: []
    };
    
    //reducers可以接收state但是绝不能修改state
    //reducers不能有异步操作也不能有与时间相关的操作,也不能对接收的参数进行修改
    //返回纯函数,纯函数指的是:给定固定输入,则输出固定,而且不会有任何副作用
    export default (state = defaultState,action) => {
        // state是上一个store中存储的数据,action是用户发过来的操作请求
        // 1、JSON.parse()用于从一个字符串中解析出json对象
        // 2、JSON.stringify()用于从一个对象解析出字符串
        if (action.type === CHANGE_INPUT_VALUE) {
            // state深拷贝
            const newState = JSON.parse(JSON.stringify(state));
            newState.inputValue = action.value;
            return newState;
        }
        if (action.type === ADD_TODO_ITEM) {
            // state深拷贝
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.push(newState.inputValue);
            newState.inputValue = '';
            return newState;
        }
        if (action.type === DELETE_TODO_ITEM) {
            // state深拷贝
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.splice(action.index, 1);
            return newState;
        }
        return state;
    }
    

      

    5、核心组件中导入store

    import React,{Component} from 'react';
    import 'antd/dist/antd.css';
    import {Input, Button, List} from 'antd';
    import store from './store/index';
    import {getInputChangeAction, getAddItemAction, getDeleteItemAction} from './store/actionCreators'
    // import {CHANGE_INPUT_VALUE , ADD_TODO_ITEM , DELETE_TODO_ITEM} from './store/actionTypes';
    
    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中数据的变化,改变则通过handleStoreChange()函数重新渲染
            store.subscribe(this.handleStoreChange)
        }
    
        render(){
            return(
                <div style={{margin:'30px'}}>
                    <div>
                        <Input
                            type="text"
                            value={this.state.inputValue}
                            placeholder='todo info'
                            style={{'300px',marginRight:'10px'}}
                            onChange={this.handleInputChange}
                        />
                        <Button type="primary" onClick={this.handleBtnClick}>提交</Button>
                    </div>
                    <div>
                        <List
                            style={{'300px',marginTop:'10px'}}
                            bordered
                            // 数据源
                            dataSource={this.state.list}
                            renderItem={(item,index) => (<List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>)}
                        />
                    </div>
                </div>
            )
        }
    
        // 输入框改变
        handleInputChange(e){
            const action = getInputChangeAction(e.target.value);
            // 将action派发给store
            store.dispatch(action);
        }
    
        // 数据重新获取并渲染
        handleStoreChange(){
            // store.getState()从store中重新取数据
            // this.setState()更新数据
            this.setState(store.getState())
        }
    
        // 点击后增添数据
        handleBtnClick(){
            // 创建action对象
            const action = getAddItemAction();
            // 将action发给store
            store.dispatch(action);
        }
    
        handleItemDelete(index){
            const action = getDeleteItemAction(index);
            store.dispatch(action);
        }
    
    }
    
    export default TodoList;
    

      

    6、升级——store中创建actionCreators

    import {ADD_TODO_ITEM, CHANGE_INPUT_VALUE, 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
    });
    

      

    7、升级——store中创建actionTypes

    export const CHANGE_INPUT_VALUE = 'change_input_value';
    export const ADD_TODO_ITEM = 'add_todo_item';
    export const DELETE_TODO_ITEM = 'delete_todo_item';
    

      

  • 相关阅读:
    sublime 下载 插件
    前端跨域
    浏览器内核
    JavaScript数据类型检测
    代码整洁之道——10、注释
    代码整洁之道——9、格式化
    代码整洁之道——8、错误处理
    代码整洁之道——7、并发
    代码整洁之道——6、测试
    代码整洁之道——5、SOLID
  • 原文地址:https://www.cnblogs.com/piaobodewu/p/9458213.html
Copyright © 2020-2023  润新知