【进阶】React使用Redux重做TodoList - ic翼

214 阅读3分钟
原文链接: bingyishow.top

不同于上一次文章,这次使用Redux实现TodoList,然后再美化一下。

最后效果

Redux

关于Redux,Redux 是 JavaScript 状态容器,提供可预测化的状态管理。可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供 超爽的开发体验。

下面Redux中代码的核心,全部都围绕这一张图进行。

1

简单理解

  • 可以直接跳到TodoList。查看具体的代码。

从上面的图中可以看到。有四个部分。直观看很难理解。但简化来看整个流程可以比作一次借书的流程。

首先蓝色的React Compontents是每个页面上的组件可以当做借书用户

棕色Action Creators是组件传递的信息,他给Store说要获取什么信息。可以当做借什么书要说的话

橙色Store是存储数据的公共区域,它接收到要获取的信息。但是他不知道从哪下手。需要传递给后面处理。可以当做图书的管理员。他知道你要借书但是因为书太多他记不住。他需要一个记录本。

紫色Reducers 是处理信息的区域。它接收到Store传递的信息。它理解该怎么去处理这些信息。可以当做图书信息的记录本

整个流程

那么从头梳理一下。

借书之前借书人必须存在(存在一个组件)

借书人说了一句话,要借什么什么。(组件传递信息要获取什么什么)

这是图书的管理员听见了,他要帮你找这本书。因为图书太多了他记不住,所以需要从记录本中查阅相关的信息。知道这本书在哪后。管理员去处理寻找。(Store接收到了信息,但是他不处理信息。给Reducers来处理。Reducers处理完成后告诉Store该怎么去修改数据)

他处理好找到了这本书后。然后把这本书给借书人。(Store知道该怎么修改数据,完成后返回给组件)


美化样式

这步可以忽略,不影响后面的实现。

传统的输入框、按钮不是特别好看。自己美化又麻烦。所以直接引用Ant Design

官网:ant.design/index-cn

使用方法

首先安装Ant Design

$ npm install antd --save
//或者
$ yarn add antd

接下来引入主样式文件,之后按需引入加载相应的独立组件即可。具体的可以到官网查看文档。这里就不过多介绍了。

import 'antd/dist/antd.css';

TodoList

实现TodoList并不难。关键是如何引入并使用Redux。

引入Redux

npm install --save redux
//安装稳定版

创建Store

首先在src目录需要创建一个文件夹store 。在store中创建index.js文件。代码如下。

import {createStore} from 'redux';
import reducer from './reducer';

//创建store
const store = createStore(
    reducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

创建reducer

同样在store下创建reducer.js文件。代码如下

const defaultState = {
    inputValue : '',
    list: []
}

//reducer 可以接受state,但是绝不能修改state
export default (state = defaultState , action) => {
    if (action.type === 'change_input_value'){
        //深拷贝
        const newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value;
        return newState;
    }
    if(action.type === 'add_todo_item'){
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
        return newState;
    }
    if (action.type === 'delete_todo_item') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index,1);
        return newState;
    }

    return state;
}

创建TodoList

src目录下创建组件TodoLis。代码如下。

import React, { Component } from 'react';
//引入Ant
import 'antd/dist/antd.css';
//引入Input
import { Input } from 'antd';
//引入自定义样式
import './css1.css'
//引入Button
import { Button } from 'antd';
//引入List
import { List } from 'antd';
//引入redux
import store from './store/index';

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.handleButtonChange = this.handleButtonChange.bind(this);
        //监听store里的数据,如果变幻执行handleStoreChange
        store.subscribe(this.handleStoreChange);
    }

    render(){
        return (
            <div className={'todo'}>
                <div>
                    <Input
                        value={this.state.inputValue}
                        placeholder={'todo info'}
                        className={'todoinput'}
                        onChange={this.handleInputChange}
                    />
                    <Button
                        type="primary"
                        onClick={this.handleButtonChange}>提交</Button>
                </div>
                    <List
                        className={'todolist'}
                        bordered
                        dataSource={this.state.list}
                        renderItem={(item,index) => (
                            <List.Item onClick={this.handleItemDelete.bind(this,index)}>
                                {item}
                            </List.Item>
                        )}
                    />
            </div>
        )
    }

    handleInputChange(e){
        const action = {
            type: 'change_input_value',
            value: e.target.value
        };
        store.dispatch(action);
    }

    handleStoreChange() {
        this.setState(store.getState());
    }

    handleButtonChange(){
        const action = {
            type: 'add_todo_item'
        };
        store.dispatch(action);
    }

    handleItemDelete(index){
        const action = {
            type : 'delete_todo_item',
            index
        }
        store.dispatch(action);
    }

}

export default TodoList;

至此就完成了Redux的TodoList小示例。