资讯专栏INFORMATION COLUMN

Redux技术架构简介

weizx / 2275人阅读

摘要:是一个程序架构,源于提出的一种架构,然而,它不仅可以应用于,还可以应用于其他任何框架中。有以下职责维持应用的提供方法获取提供方法更新通过注册监听器通过返回的函数注销监听器。同时,的返回值实际上是一个函数可以解除监听。

Redux是一个程序架构,源于Flux(Facebook提出的一种架构),然而,它不仅可以应用于React,还可以应用于其他任何框架中。值得一提的是,Redux的源代码很少,但是他的逻辑拆分和函数式编程的设计思想是非常值得学习的。

1. 解决的问题

当一个JavaScript单页应用变得越来越复杂时,我们要处理的数据(model)也变得越来越庞大,随之而来的是每个数据的状态(state)会变得难以维护。当一个model改变时,我们可能要手动处理由此引发的其他model的变化,更糟糕的是,其他model变化可能又会引起另一些model的变化,这样产生连锁反应。最后我们很容易就会不记得model在什么时候以及如何发生改变。这正是Redux可以解决的最大痛点之一—以统一的方式管理数据状态。
统一的数据状态管理体现为以下2个方面:

组件间的数据通信

UI和数据处理逻辑分离

2.三大原则

单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

State是只读的

唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

Reducer必须是纯函数

3.基本概念

Action

Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。直白的说,action就是一种消息类型,他告诉Redux是时候该做什么了,并带着相应的数据传到Redux内部(即接下来介绍的Reducer)。
Action就是一个简单的对象,其中必须要有一个type属性,用来标志动作类型(reducer以此判断要执行的逻辑),其他属性用户可以自定义,但要尽量简单。如:

{type: SET_ALL,index: 5}

Action Creator
Action Creator是一个用来自动生成Action的函数,这也是Redux函数式编程的一种体现。通常,我们会按照业务逻辑或组件把相关的Action Creator放在一个文件中,形式如下:

export const SHOW_SLIDER = "SHOW_SLIDER";
export const RIGHT_SLIDER = "RIGHT_SLIDER";

export const showSliderAction = (index) => {
    return {
        type: SHOW_SLIDER,
        index
    };
}
export const rightSliderAction = (length) => {
    return {
        type: RIGHT_SLIDER,
        length
    };
}

其中showSliderAction和rightSliderAction就是Action Creator。
由于Action Creator的形式大体相同,我们还可以创建一个用来生成Action Creator的函数以进一步简化。

export const makeCreateAction = (type, ...keys) => {
    return (...data) => {
        let action = {type};
        keys.forEach((v,i) => action[v] = data[i]);
        return action;
    }
}
export const showSliderAction = makeCreateAction(SHOW_SLIDER, index);
export const rightSliderAction = makeCreateAction(RIGHT_SLIDER, length);

Reducer
Reducer 指定了应用状态的变化如何响应 actions 并发送到 store 的,action只是告诉Redux该干什么了,并没有告诉他怎么干,而reducer就是根据action处理state如何改变的逻辑。
Reducer必须是一个纯函数(原因稍后解释),他根据action处理state的更新,如果没有更新或遇到未知action,则返回旧state;否则返回一个新state对象。注意:不能修改旧state,必须先拷贝一份state,再进行修改,也可以使用Object.assign函数生成新的state。另外,state参数需先进行初始化。实例代码如下:

//初始状态
let initialState = {hiddenClass: "g-hidden",currentIndex:0};

let sliderReducer = function (state = initialState, action) {
    switch(action.type){
        case sliderAction.SHOW_SLIDER:
            return {hiddenClass: "",currentIndex:action.index};
        case sliderAction.RIGHT_SLIDER:
            if(state.currentIndex == action.length-1){
                return Object.assign({}, state, {currentIndex:0});
            }else{
                return Object.assign({}, state, {currentIndex:Number.parseInt(state.currentIndex)+1});
            }
        default:
            return state;
    }
}

export default sliderReducer;

使用纯函数的原因:

   首先,纯函数的特点是:
       •函数的返回结果只依赖于它的参数。
       •函数执行过程里面没有副作用。(不会对外界产生影响)

如果不使用纯函数,即直接更改state值会怎么样呢?

… …      
    case sliderAction.RIGHT_SLIDER:
            if(state.currentIndex == action.length-1){
        state.currentIndex = 0;
                return state;
            }
… …

之后会发现,无论state如何变化,UI都不会更新。以下是Redux的部分源码:

通过查看Redux源码得知,新旧state的比较只是对引用地址的比较,如果reducer只是返回旧state(即previousStateForKey)的更新,新state(nextStateForKey)实际上和旧state引用的都是同一块内存地址,所以无论如何更改,新旧state始终保持相同。这就是为什么reducer必须是纯函数的原因。

Reducer拆分与合并
Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大。所以需要先对reducer进行拆分,拆分的原则可以按业务逻辑进行划分,如果是react的话,可以直接和react的组件相对应进行划分。
划分好之后,可以用Redux提供的combineReducers方法进行合并,十分方便。

import { combineReducers } from "redux";
import photomainReducer from "./photomainReducer";
import sortReducer from "./sortReducer";
import sliderReducer from "./photoSliderReducer";

export default combineReducers({
    photomainReducer,
    sortReducer,
    sliderReducer
});

Store
Store 是把Action、Reducer联系到一起的对象。Store 有以下职责:

   1.维持应用的 state;
   2.提供 getState() 方法获取 state;
   3.提供 dispatch(action) 方法更新 state;
   4.通过 subscribe(listener) 注册监听器;
   5.通过 subscribe(listener) 返回的函数注销监听器。

(1) 创建store
Redux应用应该只有一个store,他提供了创建store的API—createStore(reducer, initState)。第一个参数为一个reducer,可以接受通过combineReducers合并后的reducer,第二个是可选参数,意思是可以设置应用的初始state。

const store  = createStore(
        indexPhotomainReducer,
    );
export default store;

(2)State
应用的state也应该只有一个,里面包含了所有的应用数据。当需要获取state的时候,需要使用store.getState()方法。
(3)store.dispatch(action)
UI更新state 的唯一途径,通过dispatch方法发起action,唤起对应的reducer更新state。
(4)store. subscribe(listener)
通过此方法可以设置监听函数,一旦state发生变化,就会立即调用监听函数(listener)。同时,subscribe的返回值(实际上是一个unsubscribe函数)可以解除监听。如:

// 每次 state 更新时,打印日志
// 注意 subscribe() 返回一个函数用来注销监听器
const unsubscribe = store.subscribe(() =>
    console.log(store.getState())
)

// 停止监听 state 更新
unsubscribe();

4.数据流

(1)首先,用户发出 Action(如click事件)。

store.dispatch(SHOW_SLIDER)

(2) Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer根据Action的type调用相应的分支, 返回新的 State 。

let initialState = {hiddenClass: "g-hidden",currentIndex:0};

let sliderReducer = function (state = initialState, action) {
   switch(action.type){
       case sliderAction.SHOW_SLIDER:
           return {hiddenClass: "",currentIndex:action.index};
       default:
           return state;
   }
    }

(3) State 一旦有变化,Store 就会调用监听函数。

store.subscribe(listener);

(4) listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。

function listerner() {
  let newState = store.getState();
  component.setState(newState);   
}

以上为Redux的数据流动过程。

本篇到此告一段落,下一篇介绍Redux的异步实现。

参考

Redux 中文文档
Redux 入门教程-阮一峰

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94840.html

相关文章

  • Redux技术架构简介(二)-- 异步实现

    摘要:异步实现设计需要增加三种通知异步请求发起的异步请求成功的异步请求失败的示例代码如下返回参数完全可以自定义。这种分别在请求开始前,请求成功后,请求失败后发送。表示数据的有效性,他的作用是在异步请求发送失败后,告诉当前的数据是过时的数据。 说明:对Redux不了解的同学可先看看这篇文章Redux技术架构简介(一) 前言 这里说的Redux异步实现,是专指Redux中的异步Action实现,...

    wuaiqiu 评论0 收藏0
  • Redux概念之一: Redux简介

    摘要:应用这说明并不是单指设计给用的,它是独立的一个函数库,可通用于各种应用。在数据流的最后,要触发最上层组件的,然后进行整体的重新渲染工作。单纯在的对象上是没有办法使用,要靠额外的函数库才能这样作,这是一定要使用类似像这种函数库的主要原因。 Redux的官网中用一句话来说明Redux是什么: Redux是针对JavaScript应用的可预测状态容器 这句话虽然简短,其实是有几个涵义的: ...

    cjie 评论0 收藏0
  • React与Redux整合技术简介

    摘要:展示组件与容器组件的绑定库的基本开发思想是展示组件与容器组件相分离。技术上讲,容器组件就是使用从树中读取部分数据,并通过来把这些数据提供给要渲染的组件。 说明:阅读本篇文章需要对Redux有一定的了解,对Redux不了解的同学可先看看这篇文章Redux技术架构简介(一) 1. React中引入react-redux 为了让Redux和React更好的配合,Facebook专门开发了一个...

    idealcn 评论0 收藏0
  • 深入redux技术

    摘要:另外,内置的函数在经过一系列校验后,触发,之后被更改,之后依次调用监听,完成整个状态树的更新。总而言之,遵守这套规范并不是强制性的,但是项目一旦稍微复杂一些,这样做的好处就可以充分彰显出来。 这一篇是接上一篇react进阶漫谈的第二篇,这一篇主要分析redux的思想和应用,同样参考了网络上的大量资料,但代码同样都是自己尝试实践所得,在这里分享出来,仅供一起学习(上一篇地址:个人博客/s...

    imingyu 评论0 收藏0
  • 深入redux技术

    摘要:另外,内置的函数在经过一系列校验后,触发,之后被更改,之后依次调用监听,完成整个状态树的更新。总而言之,遵守这套规范并不是强制性的,但是项目一旦稍微复杂一些,这样做的好处就可以充分彰显出来。 这一篇是接上一篇react进阶漫谈的第二篇,这一篇主要分析redux的思想和应用,同样参考了网络上的大量资料,但代码同样都是自己尝试实践所得,在这里分享出来,仅供一起学习(上一篇地址:个人博客/s...

    VPointer 评论0 收藏0

发表评论

0条评论

weizx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<