React---Redux的使用

Redux 的适用场景:多交互、多数据源。

Redux对于JavaScript应用而言是一个可预测状态的容器。换言之,它是一个应用数据流框架,而不是传统的像underscore.js或者AngularJs那样的库或者框架。

Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,一个新的对象就会被创建(使用actions和reducers)。

redux 是一个范用的状态管理框架
主要是解决了组件间状态共享的问题
原理是集中式管理
不是所有的项目都需要使用redux

redux的流程

View调用store.dispatch发起Action->store接受Action(action传入reducer函数,reducer函数返回一个新的state)->通知store.subscribe订阅的重新渲染函数
在这里插入图片描述

redux和flux的区别

Redux和Flux很像。主要区别在于Flux有多个可以改变应用状态的store,它通过事件来触发这些变化。组件可以订阅这些事件来和当前状态同步。
Redux没有分发器dispatcher,但在Flux中dispatcher被用来传递数据到注册的回调事件。另一个不同是Flux中有很多扩展是可用的,这也带来了一些混乱与矛盾
在redux当中只能定义一个可以更新状态的store
flux可以定义多个仓库
redux把store和Dispatcher合并,结构更加简单清晰
新增state,对状态的管理更加明确

redux和vuex的区别

改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer,无需switch,只需在对应的mutation函数里改变state值即可
由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的State即可

redux的优点

redux把流程规范了,统一渲染根节点虽然对代码管理上规范了一些,只要有需要显示数据的组件,当相关数据更新时都会自动进行更新。

减少手动编码量,提高编码效率。

redux的缺点

一个组件所需要的数据,当相关数据更新时,组件要重新render,可能会有效率影响,或者需要写复杂的shouldComponentUpdate进行判断。

redux

redux中有三个基本概念,Action,Reducer,Store。
store 仓库
维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
通过 subscribe(listener) 注册监听器。
action 中发送过来的对象 必须有一个type属性
reducer 他是一个纯函数 他会跟action发送过来的type类型做逻辑上的处理(使用switch方法进行判断)

Redux核心API-reducer

Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。

约束:

1、不得改写参数
2、不能调用系统 I/O 的API
3、不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

Reducer 函数里面不能改变 State,必须返回一个全新的对象,请参考下面的写法。

// State 是一个对象
function reducer(state, action) {
  return Object.assign({}, state, { thingToChange });
  // 或者
  return { ...state, ...newState };
}
// State 是一个数组
function reducer(state, action) {
  return [...state, newItem];
}

安装 npm install redux -D

一、Redux核心API

引入必要组件:

import { createStore} from 'redux';

生成store:

const store = createStore(reducer,  state初始状态[可选]);

取得当前时刻的state:

const state = store.getState();

发出action

store.dispatch({
  type: 'ADD_TODO',
  text: 'Learn Redux'
});

设置监听函数:

store.subscribe(callback);

二.Reducer拆分

import {combineReducers} from 'redux';
Const reducer=combineReducers({
Xxx:xxx(函数-业务逻辑)
})

二.Middleware的由来

1、middleware的由来

在redux里,action仅仅是携带了数据的普通js对象。action creator返回的值是这个action类型的对象。然后通过store.dispatch()进行分发。
同步的情况下一切都很完美,但是reducer无法处理异步的情况。
例如:我希望点击一个按钮,2秒之后更新视图,显示消息“Hi”。
那么我们就需要在action和reducer中间架起一座桥梁来处理异步。这就是middleware

2、理解middleware机制

参考代码:

export default function thunkMiddleware({ dispatch, getState }) {
  return next => action =>
    typeof action === 'function' ?
      action(dispatch, getState) :
      next(action);
}

这段代码的意思是,中间件这个桥梁接受到的参数action,如果不是function则和过去一样直接执行next方法(下一步处理)。相当于中间件没有做任何事。
如果action是function,则先执行action,action的处理结束之后,再在action的内部调用dispatch。

三. Redux异步流

使用middleware简化异步请求

使用middleware处理复杂异步流

redux-thunk:
store.dispatch参数可以是一个function
使用方法:
1.引入:

import thunk from 'redux-thunk';

2.加入中间件

const store = createStore(fetchReducer, applyMiddleware(thunk));

在这里插入图片描述

Actions.js

var Action={
    addItem(text){
        return{
            type:'ADD_TODO',
            text:text
        }
    },
    rmItem(text){
        return{
            type:'RM_TODO',
            text:text
        }
    },
    loginItem(text){
        return{
            type:"ADD_Login",
            text:text
        }
    },
    addCount(text){
        return{
            type:"ADD_Count",
            text:text
        }
    }
    
}

export default Action;

Demo.js

Demo.js
import React from  "react";
import Action from  "./Action"  //把数据传给Action处理一下
import Store from "./Store";
class Demo extends React.Component{
    constructor(props){
        super(props)
        //把start中所有的数据都给取出来
        this.state={
           // arr:Store.getState() //合并的写法
            arr:Store.getState().list,
            user:Store.getState().users,
            count:Store.getState().count
        }
        this.changes = this.changes.bind(this)
    }
    changes(){
        //修改setState的时候
        this.setState({arr:Store.getState().list,user:Store.getState().users,count:Store.getState().count})
    }
    componentDidMount(){
        Store.subscribe(this.changes)  //监听
    }
    add(){
        Store.dispatch(Action.addItem(this.refs.ipt.value))  //数据给store的dispatch方法接收
        this.refs.ipt.value=""
    }
    del(i){
        Store.dispatch(Action.rmItem(i))
    }
    login(){
        Store.dispatch(Action.loginItem(this.refs.username.value))
        this.refs.username.value=""
    }
    tap(){
        Store.dispatch((dispatch)=>{  //用来操作异步操作
            setTimeout(() => {
                dispatch(Action.addCount(1))
            }, 2000);
        })

    }
    
   
    render(){
        var _this = this;
        return(
            <div>
                <h1>Redux----{this.state.user}</h1>
                <input type="text" ref="ipt"/>
                <div>
                    用户名:<input type="text" ref="username"/>
                    <button onClick={this.login.bind(this)}>登陆</button>
                </div>
            
                <button onClick={this.add.bind(this)}>增加</button>

                <hr/>
                <p>{this.state.count}</p>
                <button onClick={this.tap.bind(this)}>累加</button>

                {
                   this.state.arr.map(function(item,i){
                    return(
                        <div key={i}>{item}----<button onClick={_this.del.bind(_this,i)}>删除</button></div>
                    )
                })
                }
            </div>
        )
    }
}

export default Demo;

Reducer.js

import {combineReducers} from "redux";  //拆分写法
import TodoList from "./TodoList"
import TodoLogin from "./TodoLogin"
import TodoCount from "./TodoCount"
// var Reducer = function (state=[],action) {   //写在一起的
//     switch (action.type) {  //判断actoin的type类型
//         case 'ADD_TODO':     //添加
//             let newstate = [...state];  //拷贝原本的state
//             newstate.push(action.text)
//             return newstate;   //判断是否符合,符合返回newstate
//         case 'RM_TODO':      //删除
//             let newstateS = [...state];  //拷贝原本的state
//             newstateS.splice(action.text,1)
//             return newstateS;   //判断是否符合,符合返回newstate
//         default:
//             return state;
            
//     }
// }
//当前数据为空,当有新数据传来的时候往数组里面push


var Reducer = combineReducers({
    list:TodoList,
    users:TodoLogin,
    count:TodoCount
})



export default Reducer;

Store.js

import {createStore,applyMiddleware} from 'redux';  //创建store
import thunk from 'redux-thunk'; //处理异步
import Reducer from "./Reducer";

var Store=createStore(Reducer,applyMiddleware(thunk))  //允许异步请求,必须安装依赖redux-thunk

export default Store

TodoList.js

var TodoList = function(state=[],action) {   //写在一起的
    switch (action.type) {  //判断actoin的type类型
        case 'ADD_TODO':     //添加
            let newstate = [...state];  //拷贝原本的state
            newstate.push(action.text)
            return newstate;   //判断是否符合,符合返回newstate
        case 'RM_TODO':      //删除
            let newstateS = [...state];  //拷贝原本的state
            newstateS.splice(action.text,1)
            return newstateS;   //判断是否符合,符合返回newstate
        default:
            return state;
            
    }
}

export default TodoList;

TodoLogin.js

var TodoLogin=(state='',action)=>{
    switch (action.type){
        case 'ADD_Login':
            let newstate=state
            newstate=action.text;
            return newstate;
        default:
            return state;
            
    }
}

export default TodoLogin;

TodoCount.js

var TodoCount=(state=1,action)=>{
    switch (action.type){
        case 'ADD_Count':
            let newstate=state;
            newstate+=action.text;
            return newstate
        default:
            return state
    }
}

export default TodoCount;

猜你喜欢

转载自blog.csdn.net/qq_42697338/article/details/86535526