Redux

REDUX

1.redux究竟是个什么玩意 ?

​ 如果要谈起redux,我们必须要了解什么叫做 函数式编程 ,其实我们程序的组件开发属于函数式编程的升级版,函数式编程带给我们的优势可以说非常之多,什么功能划分更容易,什么维护更简便,什么高内聚低耦合等等优势在此不再赘述,主要谈一谈函数式编程的缺点。

1. 函数式编程容易编程链式调用的模式。
function foo(){
    var  a = funA();
    var  b = funB();
    return funC(b);
}
function funA(arg){
    return arg + 1;    
}
function funB(arg){
    return arg + 2;
}
function funC(arg){
    return arg + 3;
}

​ 类似于这样的函数在开发之中带给我们的困扰可以说是相当之多了,那么问题来了,我们为什么要用这样的模式编写函数那?

​ 因为函数的作用域是独立的, 所以我们在函数之间进行数据通讯的时候往往需要通过传递参数或者使用bind等方法进行参数传递,这样的方式带给我们的就是函数之间的紧密耦合,如何进行解耦那,我们需要用到全局变量进行函数之间值的传递, 可是这样真的解决问题了么?

​ 这样的做法解决了一个问题,但是其他问题就会如雨后春笋一般冒出来,全局变量浪费内存,全局变量不安全,全局变量.... ,办法总比困难多,对于这样的数据共享我们其实可以使用订阅发布模式解决问题,但是订阅发布就万无一失了么?

2. 数据驱动模型的实现。
数据驱动.png

​ 对于这样的需求我们往往需要使用订阅发布模式进行实现,但是订阅发布的封装又出现了n种方案,怎么办?

​ 其实说到这里我们好像知道了一件事,问题的解决方案有了,但是我们实际上是欠缺一个统一的标准对我们的需求(函数与函数或者组件与组件之间的通讯)进行统一,这个标准不一定是最优的但是需要应用范围要广。

​ 这个时候flux架构出现了。

2. flux架构

flux架构就像是眼镜,你自然知道什么时候需要他

​ flux的横空出世好像是踏着五彩祥云的至尊宝,拯救万千前端于水火之中,但是这个至尊宝有点麻烦。

flux架构.png

​ 这是flux的架构图,你甚至不需要看懂,只需要知道整个架构的复杂程度还是非常高的,在flux之中想要更改数据仓库(store),我们需要调用dispather,在dispather之中手动调用 store之中的set方法,去更改状态,我们在开发企业级项目的时候,往往会维护一个非常庞大的store,这时候我们面对这样异常敏感而且不易排错的功能,可以说如履薄冰。

​ 然后钢铁侠替代至尊宝来接你了。

3.redux

​ 可以说redux就是flux架构的简化版,虽然还是很难,但是相对flux而言,redux把一些易错的操作进行了内部封装,这些封装使得报错风险急剧下降。

​ 比较现成的东西就一定是量身订造的东西,虽然redux可以完全独立使用,可以配合任何框架实现基础功能但是我们最多的使用redux的地方还是在react之中,为啥那?

​ 我们考虑的框架有两款,vue有比较现成的vuex, react那, fb的工程师更推荐使用redux,因为redux和react有更高的契合度有更丰富的合作生态如 react-redux等。

4. redux使用详解

**part 1 : 看懂一张图 **

image.png

​ 这张图基本说明了使用redux的全部内容,但是想要读懂这张图可能对于绝大多数小伙伴来说比较困难,怎么办呐? 不要放弃,我们先学一下基本操作,过一会再回头来看这张图。

  1. redux 是干嘛的 ?

    一句话解释 : 其实redux就是用来进行函数,组件之间数据共享的。

    1. redux怎样进行数据共享那 ?

    一句话解释 : 就是把一个对象放进数据仓库之中。

    1. redux是否实现了发布订阅模式那 ?

    一句话解释 : 实现了,这是后话。

所以我们大致了解了redux,那么我们用一个极简的翻译来看一下这个图。

中文redux示意图.png

这张图之中尤其要注意的是创建状态状态区分处理器, 这两个部分之间的绿色箭头,在通过数据仓库时这个线是虚的,也就是说,本质上来讲是状态区分处理器最终将状态放入了数据仓库之中,可是为什么这条线要先经过数据仓库那 ?

​ 敲黑板的重点来了 :

​ 创状态这个功能其实会创建一个对象,这个对象会被 dispatch方法直接派发到 数据仓库之中,但是数据仓库又需要去进行一个状态区分和处理,这个区分和处理是被直接集成在数据仓库之中的,相当于仓库分拣员 , 这个分拣员会自动将创建好的对象进行分类,分类后放入仓库。

数据仓库内部一旦发生改变了,那么视图就会发生相应的改变,这就是redux完整的流程。

但是这个完整的流程之中有非常之多的注意事项,如果你已经理解了以上的内容,那么就可以继续向下学习redux操作实例了。

为了方便操作,我们使用 create-react-app 脚手架工具搭建react环境,并使用 redux进行开发 , 编写redux实例,同时为了使用的安全和严谨,请务必参考 redux官方文档,其余野路子博客不建议查看。

redux官方文档

part 2 : 记得三个单词

​ 1. action 这货就是我们刚才说的数据对象,这个对象就是JavaScript的单纯的对象。 就是下面这样的

var action = {
    name : "一个对象"    
}
2. action 还有一些小小的矫情,就是必须有某些东西,这个东西就叫做 `type`, 我们在创建action的时候通常会创建这样的一个对象
let action = {
    type : MY_FIRST_ACTION,
    payload : {
        text : "随便写一些文本"
    }
}

我们写的这个对象大概就是action了,但是我们想要创建茫茫多个action怎么办呐 ? 记得我们有一个创建器就好了,这个创建器叫做 actionCreater

3. actionCreate长成这样 , 我们通常定义 action之中type的时候会使用`常量`。

action.js

/*
*   常量定义,这个常量仅代表状态。
*/
export const INCREASE_NUMBER = "INCREASE_NUMBER";
export const REDUCE_NUMBER = "REDUCE_NUMBER";
export const INIT_NUMBER = "INIT_NUMBER";

export function increaseNumber(number){
    return {
        type : INCREASE_NUMBER,
        payload : {
            number 
        }
    }
}

export function reduceNumber(number){
    return {
        type : REDUCE_NUMBER,
        payload : {
            number 
        }
    }
}
4. 我们要设计一下我们当前state 的数据结构,这个数据结构方便我们后续的操作。
{
    calculationNumber :{
        type : INIT_NUMBER,
        payload : {
            number : 0
        }
    }
}

这大概就是一个及其简单的数据结构了。

5. 开发状态区分处理器 reducer

​ reducer接受两个参数 reducer( prevState, state) , 即为原始状态和更新状态 , 请务必记住reducer的特性,reducer是一个纯函数,这意味着 同样的输入,同样的输出,如果输入同样的内容那么输出一定是一致的,这就是纯函数。 在这里不能调用 Date.now() ,或者 Math.random() 等方法。

reducer.js

import {
    INCREASE_NUMBER,
    REDUCE_NUMBER,
    INIT_NUMBER
} from "./action"

function calculation(state = initialState , action){
    switch(action.type){
        case INCREASE_NUMBER : 
            return Object.assign({},state,{
                ...action,
                payload : {
                    number : state.payload.number ++
                }
            });
        case REDUCE_NUMBER : 
            return Object.assign({},state,{
                ...action,
                payload : {
                    number : state.payload.number --
                }
        });
        default : return state;
    }
}

export calculation;

6. 最后我们引入我们的主角

store.getState()用来获取store完整数据。

store.subscribe() 用来监听完整数据。

import {createStore} from "redux";
import reducer from "./reducer";
let store = createStore(reducer);

你可能感兴趣的:(Redux)