Redux学习1

目录

1.概述

2.Redux工作流程

3.使用antd编写TodoList页面布局

4.Redux实现TodoList

5.ActionTypes的拆分

6.使用actionCreator统一创建action

7.Redux设计和使用的三项原则:


1.概述

Redux:数据层框架。

Redux = Reducer + Flux

核心:将所有数据放到公共store中,蓝的组件改变store中数据,灰的组件自动感知数据变化,获取数据,进而发生改变,实现间接的组件间数据传递功能。

2.Redux工作流程

3.使用antd编写TodoList页面布局

antd:https://ant.design/docs/react/introduce-cn

使用前先安装:npm install antd --save​​​​​​​(使用插件之前一定先进行安装)

4.Redux实现TodoList

首先安装redux:npm install --save redux

(1)创建store

(2)Action 和 Reducer 的编写

(3)React + Redux实现TodoList实例

(此例中尚不完整,尚不完全合理,有待进行ActionTypes的拆分 和 actionCreator的统一创建)

1.目录结构

              

2.index.js(入根组件,入口)

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';

ReactDOM.render(<TodoList />, document.getElementById('root'));

3.TodoList.js(组件)

import React, {Component} from 'react';
import 'antd/dist/antd.css';
import {Input, Button, List} from 'antd';
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.handleButtonClick = this.handleButtonClick.bind(this);
        store.subscribe(this.handleStoreChange)  //store中数据改变后执行的方法
    }

    render() {
        return (
            <div style={{marginTop: 10, marginLeft: 10}}>
                <div>
                    <Input value={this.state.inputValue}
                           placeholder="todo info"
                           style={{width: 300, marginRight: '10px'}}
                           onChange={this.handleInputChange}/>
                    <Button type="primary" onClick={this.handleButtonClick}>提交</Button>
                    <List style={{marginTop: 10, width: 300}}
                          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 = {
            type: 'change_input_value',
            value: e.target.value
        };
        store.dispatch(action);
    }

    handleStoreChange(){
        this.setState(store.getState());  //执行setState后,页面才会重新渲染
    }

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

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

export default TodoList;

4.store/index.js(创建store)

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

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

export default store;

5.store/reducer.js(Reducer)

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

//reducer 可以接受state,但绝不能修改state,所以进行拷贝后修改
export default (state=defaultState, action)=>{   //state数据、action都是从store中来的
    if(action.type==='change_input_value'){
        const newState = JSON.parse(JSON.stringify(state));//深拷贝state??
        newState.inputValue = action.value;
        return newState;  //将改变的state返回给store
    }
    else if(action.type==='add_todo_item'){
        const newState = JSON.parse(JSON.stringify(state));//深拷贝state??
        newState.list.push(newState.inputValue);
        // newState.list = [...newState.list, newState.inputValue];  //这种方法也可以
        newState.inputValue = '';
        return newState;
    }
    else if(action.type==='del_todo_item'){
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index,1);
        return newState;
    }
    return state;
}

5.ActionTypes的拆分

由于在编写代码时,action中的type字符串容易写错,导致程序不能运行;可以在actionTypes.js中定义type字符串的常量,在定义action的type时,可以使用常量,这样不容易出错。

//TodoList.js
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DEL_TODO_ITEM} from './store/actionTypes';

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


//actionTypes.js(新增的用于定义常量的)
export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DEL_TODO_ITEM = 'del_todo_item';


//reducer.js
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DEL_TODO_ITEM} from './actionTypes';

if(action.type === CHANGE_INPUT_VALUE){
        const newState = JSON.parse(JSON.stringify(state));//深拷贝state??
        newState.inputValue = action.value;
        return newState;  //将改变的state返回给store
    }

6.使用actionCreator统一创建action

在上述事例中(4.Redux实现TodoList),在TodoList.js 中需要多次创建action,应该使用actionCreator统一创建action。完整实例如下:

(1)目录结构

(2)index.js(同上)

(3)TodoList.js

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';

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.handleButtonClick = this.handleButtonClick.bind(this);
        store.subscribe(this.handleStoreChange)  //store中数据改变后执行的方法
    }

    render() {
        return (
            <div style={{marginTop: 10, marginLeft: 10}}>
                <div>
                    <Input value={this.state.inputValue}
                           placeholder="todo info"
                           style={{width: 300, marginRight: '10px'}}
                           onChange={this.handleInputChange}/>
                    <Button type="primary" onClick={this.handleButtonClick}>提交</Button>
                    <List style={{marginTop: 10, width: 300}}
                          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);
        store.dispatch(action);
    }

    handleStoreChange(){
        this.setState(store.getState());  //执行setState后,页面才会重新渲染
    }

    handleButtonClick(){
        const action = getAddItemAction();
        store.dispatch(action)
    }

    handleItemDelete(index){
        const action = getDeleteItemAction(index)
        store.dispatch(action)
    }
}

export default TodoList;

(4)store/index.js(同上)

(5)store/reducer.js

import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DEL_TODO_ITEM} from './actionTypes'

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

//reducer 可以接受state,但绝不能修改state,所以进行拷贝后修改
export default (state=defaultState, action)=>{   //state数据、action都是从store中来的
    if(action.type === CHANGE_INPUT_VALUE){
        const newState = JSON.parse(JSON.stringify(state));//深拷贝state??
        newState.inputValue = action.value;
        return newState;  //将改变的state返回给store
    }
    else if(action.type === ADD_TODO_ITEM){
        const newState = JSON.parse(JSON.stringify(state));//深拷贝state??
        newState.list.push(newState.inputValue);
        // newState.list = [...newState.list, newState.inputValue];  //这种方法也可以
        newState.inputValue = '';
        return newState;
    }
    else if(action.type === DEL_TODO_ITEM){
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index,1);
        return newState;
    }
    return state;
}

(6)store/actionTypes.js

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DEL_TODO_ITEM = 'del_todo_item';

(7)store/actionCreator.js

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

7.Redux设计和使用的三项原则:

(1)store是唯一的;

(2)只有store能够改变自己的内容;(当Reducer处理完数据后,将其返回给store,store根据返回的数据自己更新自己的数据;而state就是store中的数据,因此传给Reducer的是state,并且处理数据时要拷贝state,以免改变store中的state数据。)

(3)Reducer必须是纯函数。(纯函数:给定固定的输入,就一定会有固定的输出,而且不会有任何副作用。)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值