Redux自述

2 篇文章 0 订阅

一、Redux概念简述

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。简单来说,redux 就是一个储存数据的仓库,专注于状态管理,和 react 解耦。并且 redux 是单一状态,单向数据流的。

Redux要求把数据放到公共存储区域Store里,组件中尽量少放数据。当蓝色组件修改公共数据时,Store中的值发生改变,其他使用到该数据的组件到Store中取修改后的值即可。

Redux设计理念图
Redux设计理念
安装

$ yarn add redux
//或者也可以
$ cnpm install --save redux

附加包

多数情况下,可能还需要使用 React 绑定库和开发者工具。

$ cnpm install --save react-redux
$ cnpm install --save-dev redux-devtools

redux 中有4个核心概念,分别是: storestateactionreducer

  • store 指的是存储数据的仓库,我们的数据只有放在这里才可以被 redux 管理起来。Redux 提供了一个createStore来生成Store。其中createStore接收一个reducers.
  • state 指的是初始化的数据,这里的初始化数据是可以有多个的。
  • action 指的是需要变化的数据,必须要有一个type参数和一些需要在state中修改的属性。
  • reducer 因为 store 在收到我们传递过去的 action 之后需要对 state 进行更新,这个计算过程就叫做 reducer。reducer是一个函数,接受 stateaction 作为参数,返回一个新的 state.

二、Redux工作流程

在这里插入图片描述

  • ReactComponents:每个组件(理解:借书的人)
  • Store:存储数据的公共区域(理解:图书管理员)
  • Action Creators:组件想获取的数据(理解:说的要借的书的话)
  • Reducers:Store查询的内容(理解:管理员查看书的记录本)

工作流程:可以看做是你到图书馆借书,你是借书的人[React Components],你说了一句你想借什么书[Action Creators],告诉图书管理员[Store],图书管理员查看他的记录本[Reducers],并返回给你你要的书。

在这里插入图片描述

用户在 view 层通过 store.dispatch 来发送 action ,当 store 接收到用户传递过来的 action 后,会把 stateaction 传给 reducer ,而 reducer 会根据 actiontype,来返回一个新的 state。而当 store 有变化的时候,store 就会调用监听函数 store.subscribe,从而使得 view 层发生变化。

model

模型,用于保存状态;注意:不能直接修改model中的值。

{ 
	todos: [{ 
		text: 'Eat food', 
		completed: true 
	}, {
		text: 'Exercise', 
		completed: false 
	}], 
	visibilityFilter: 'SHOW_COMPLETED' 
}

action

如果想要修改 model 中的值,必须发起一个 action,这里需要注意的是 Action 实际上是一个普通的 js 对象。使用 action 来修改state的好处在于可以很清楚的描述发生了什么事情,例如 type 取值为 ‘ADD_TODO’ ,那我们就明白要添加 TODO,text 值为 TODO 的内容。

{ type: 'ADD_TODO', text: 'Go to swimming pool' } 
{ type: 'TOGGLE_TODO', index: 1 } 
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

action 是数据从应用传递到 store 中的有效载荷。它是 store 数据的唯一来源!一般来说你会通过 store.dispatch() 将 action 传到 store。Action 本质上是一个对象,但是我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。除了 type 字段外,action 对象的结构完全由你自己决定。

let action = {
	type:'TO_ADD'  //action的名字
	...
}

dispatch

传入数据,里面的参数是一个对象的形式,action 和要传入的值 比如 store.dispatch({ type:'GET_ALL', text:data }), data 就是我们要存入store的数据 这样就是把数据存在仓库里面了,这个项目中的任意组件就都可以直接得到他的数据了。

store.dispatch(action);

getState

直接打印它得到的就是全部的数据,就是我们之前定义的一个对象的形式 如果想要得到某一条的数据,比如我们刚刚储存进去的 data 直接使用store.getState().all就可以得到刚刚储存的数据。

constructor(props) {
	super(props);
	this.state = store.getState();
}

subscribe

订阅者模式,store中的数据一更改,页面的订阅者发现,就去改页面的数据,让页面重新去渲染。

constructor(props) {
	super(props);
	this.state = store.getState();
	store.subscribe(this.changeState);  //订阅者做的事情
}
//store中的数据更改后的处理函数
changeState = () => {
	...
}

三、Redux知识补充

Redux在设计和使用时有三个基本原则

  • store 是唯一的
    所有组件均使用这一个store
  • 只有 store 能够改变自己的内容
    reducer 拿到之前的数据并生成新的数据,将新的数据返回给 store,store 拿到新的数据并更新
  • Reducer 必须是纯函数
    纯函数:给定固定的输入,就一定有固定的输出,而且不会有任何副作用(副作用指的是对参数的修改)。reducer 导出的就是纯函数,给定了具体的 state 和 action,一定有固定的输出内容,且在函数内部不会修改参数的值。

四、项目示例- - -备忘录

index.js

//[store/index.js]
//创建store仓库
import {createStore} from 'redux';
import reducer from './reducer';

//将reducer与store绑定,创建store并返回
export default createStore(reducer);

reducer.js

//[store/reducer.js]
import util from '../utils/util';
//函数 reducer
const initState = {
    inputValue:'',
    listData:[{
        text:'备忘录1',
        time:'2019-09-11 09:58:36',
        status:'未完成'
    },{
        text:'备忘录2',
        time:'2019-08-27 16:38:09',
        status:'已完成'
    }]
};
export default (state=initState,action)=>{
    if (action.type === 'TO_CHANGE_INPUT'){
        let obj = {
            ...state,
            inputValue:action.value
        };
        // console.log(obj);
        return obj;
    }
    if (action.type === 'TO_ADD') {
        //修改仓库
        let obj = {
            text:state.inputValue,
            time: util.parseData(),
            status:'未完成'
        };
        let {listData} = state;
        listData.push(obj);
        return {
            ...state,
            listData,
            inputValue:''
        }
    }
    if (action.type === 'TO_DELETE') {
        let {listData} = state;
        listData.splice(action.index,1);
        return {
            ...state,
            listData
        }
    }
    if (action.type === 'TO_CHANGE_STATUS') {
        let {listData} = state;
        listData[action.index].status = '已完成';
        return {
            ...state,
            listData
        }
    }
    return state;
}

util.js

//[utils/util.js]
//获取当前时间
function parseData(){
    let date = new Date();
    let year = date.getFullYear();
    let month = date.getMonth()+1;
    let day = date.getDate();
    let hours = date.getHours();
    let minutes = date.getMinutes();
    let seconds = date.getSeconds();
    return year+'-'+formatNum(month)+'-'+formatNum(day)+' '+formatNum(hours)+':'+formatNum(minutes)+':'+formatNum(seconds);
}

//时间格式化处理
function formatNum(num){
    return num>10?num:('0'+num);
}
export default {
    parseData
}

ToDo.js

//[components/ToDo.js]
import React, { Component } from 'react';
import {Button, Input, List} from 'antd';
import store from '../store';
class ToDo extends Component {
    constructor(props) {
        super(props);
        this.state = store.getState();
        store.subscribe(this.changeState); //订阅者做的事情
    }
    inputChange = (e)=>{
        //获取input数据,更改store中的数据
        let action = {
            type:'TO_CHANGE_INPUT',
            value:e.target.value
        };
        //分发action
        store.dispatch(action);
        // console.log(this.state);
        
    }
    changeState =()=>{
        this.setState({
            ...store.getState()
        });
    }
    toAdd = ()=>{
        let action = {
            type:'TO_ADD'
        };
        store.dispatch(action);
    }
    toDelete = (index)=>{
        let action = {
            type:'TO_DELETE',
            index
        };
        store.dispatch(action);
    }
    toChangeStatus = (index)=>{
        let action = {
            type:'TO_CHANGE_STATUS',
            index
        };
        store.dispatch(action);
    }
    render() {
        return (
            <div style={{padding:20}}>
                <h2>备忘录</h2>
                <div>
                    <Input type="text" value={this.state.inputValue} onChange={this.inputChange} style={{width:200}}/>
                    <Button type="primary" onClick={this.toAdd}>添加</Button>
                </div>
                <div style={{marginTop:10}}>
                    <List size="small"
                        bordered
                        dataSource={this.state.listData}
                        renderItem={(item, index) => (
                            <List.Item>
                                <List.Item.Meta
                                title={<span style={{ color: item.status === '未完成' ? 'red' : 'green' }}>[{item.status}]&nbsp;&nbsp;{item.text}&nbsp;&nbsp;{item.time}</span>}
                                />
                                <div>
                                    {
                                        item.status === '未完成' && <Button type="link" onClick={this.toChangeStatus.bind(this, index)}>完成</Button>
                                    }
                                    <Button type="link" onClick={this.toDelete.bind(this, index)}>删除</Button>
                                </div>
                            </List.Item>
                        )}
                    />
                </div>
            </div>
        );
    }
}
export default ToDo;

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值