Flux => Redux

2020-05-08  本文已影响0人  learninginto

Flux => Redux

上一篇文章中,提到了React中的Flux架构,尽管理解起来相对容易,但是随着项目体系的增加,需要实时地将容器组件(处理页面逻辑)与UI组件(负责页面渲染)分离,手动地来降低各个模块之间的耦合度。

而Redux的出现,解决了过于复杂地拆分,可以更高效地管理多个store,并且不需要对每个视图更新函数做绑定。

  1. Web 应用是一个状态机,视图与状态是一一对应的。

  2. 所有的状态,保存在一个对象里面(唯一数据源)。

注意:flux、redux都不是必须和react搭配使用的,因为flux和redux是完整的架构,在学习react的时候,只是将react的组件作为redux中的视图层去使用了。

一、为什么要使用Redux

简单说,如果你的UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。

  1. 用户的使用方式复杂
  2. 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  3. 多个用户之间可以协作
  4. 与服务器大量交互,或者使用了WebSocket
  5. View要从多个来源获取数据
  1. 个组件的状态,需要共享
  2. 某个状态需要在任何地方都可以拿到
  3. 一个组件需要改变全局状态
  4. 一个组件需要改变另一个组件的状态
  1. Single Source of Truth(唯一的数据源)
  2. State is read-only(状态是只读的)
  3. Changes are made with pure function(数据的改变必须通过纯函数完成)

二、快速上手

redux.png

当组件要修改数据的时候,通过ActionCreators中的dispatch发送action给store,但是store的内部将action传递给了reducers,reducers进行了数据的更改,将新的state返回给store,由于store中的数据中响应式的,最后通过store通知view再次更新视图。

cnpm i redux -S

store是一个对象,里面有几个常用的函数:getState / dispatch / subscribe

参数:回调函数reducers

import {createStore} from "redux";
import reducers from "./reducers"
const store = createStore(reducers);

export default store;
  1. 必须是一个纯函数(输入一定,输出也一定),函数中有两个参数:1. state 2. action;Redux为了防止报错,默认给了参数初始值 。

  2. 当前函数必须有一个默认的state

  3. 纯函数内部的state只允许读,不允许修改

  4. 不能调用系统 I/O 的API

  5. 当前函数必须要返回一个state,返回的state会替换原来的state

    state = reduce(state , action)

//存储初始的数据
const defaultState = {
    n:10
}

export default (state=defaultState,action)=>{
    switch(action.type){
        case "NUM_ADD":
          var numState = JSON.parse(JSON.stringify(state));
          numState.n++;
          return numState;
    }
    return state
}
import React, { Component } from 'react'
import store from "./store"

export default class App extends Component {
  constructor() {
    super();
    this.state = store.getState();
    store.subscribe(this.handleUpdate.bind(this))
  }
  render() {

    let { n } = this.state;
    return (
      <div>
        <h2>{n}</h2>
        <button onClick={this.handleClick.bind(this)}>点击</button>
      </div>
    )
  }
  handleClick() {
    var action = {
      type: "NUM_ADD"
    }
    store.dispatch(action);
  }
  handleUpdate() {
    this.setState(store.getState())
  }
}

三、combineRedux

因为一个应用中只能有一个大的state,这样的话reducer中的代码将会特别多。简单概括,该方法用来合并多个reducers

  1. 分离reducer的时候,每一个reducer维护的状态都应该不同
  2. 通过store.getState获取到的数据也是会按照reducers去划分的
  3. 划分多个reducer的时候,默认状态只能创建在reducer中,因为划分reducer的目的,就是为了让每一个reducer都去独立管理一部分状态
cnpm i redux-devtools-extension -D
import { createStore, combineReducers } from "redux"
import { composeWithDevTools } from "redux-devtools-extension";
import { createStore, combineReducers } from "redux";
import { composeWithDevTools } from 'redux-devtools-extension';
//combineReducers 合并多个reducers
import num from "./reducers/num"
import todo from "./reducers/todo"

const reducers = combineReducers({
    num,
    todo
})
const store = createStore(reducers, composeWithDevTools());

export default store;

四、Redux封装

store中要返回一个对象,包含三个常用的方法getState/dispatch/subscribe

import { createStore, combineReducers } from "../redux/index"
import num from "./reducers/num"
import todo from "./reducers/todo"

const reducers = combineReducers({
    num,
    todo
})
const store = createStore(reducers);

//store应该是一个对象  getState dispatch  subscribe
export default store;

这里的state要有默认值defaultState,没有时为undefined(注意:不能赋值为null)

const defaultState = {
    n: 10
}
export default (state = defaultState, action) => {
    switch (action.type) {
        case "NUM_ADD":
            var numState = Object.assign({}, state);
            numState.n++;
            return numState;
    }
    return state;
}

上面的action中默认有一个初始值。

getState返回state值;

subscribe监听eventList中的函数;

dispatch接收action,传入state和action触发reducer处理逻辑

var initAction = { type: "@@/redux" }

export const createStore = (reducer) => {

    let eventList = [];
    let state = {};//默认为undefined

    // 返回state
    let getState = () => state;
    // 监听eventList中的函数
    let subscribe = (callback) => {
        eventList.push(callback);
    }

    let dispatch = (action) => {
        state = reducer(state, action);
        eventList.forEach(cb => {
            cb();
        })
    }

    // dispatch第一次默认会调用
    dispatch(initAction);

    return {
        getState,
        subscribe,
        dispatch,
    }
    
    //combineReducers的返回值是一个函数
    export const combineReducers = (reducers)=>{
        var newState = {};
        return (state,action)=>{
            for(var key in reducers){
                newState[key] = reducers[key](state[key],action);
            }
            return newState;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读