【转】关于Redux

一、Redux

前端框架->React->插件

  在MVC的世界里,React相当于View的部分,只涉及到页面的渲染,一旦需要涉及到应用的数据管理,还是需要交给Model和Controller,但是Redux并不是一个MVC框架,它用一种新的思路来管理数据。

 

MVC

  MVC是业界广泛接受的一种前端应用框架类型,这种框架把应用分为三个部分:

  Model(模型)负责管理数据,大部分业务逻辑应该放在Model中

  View(视图)负责渲染用户页面,应该避免在View中涉及业务逻辑

  Controller(控制器)负责接受用户输入,根据用户输入调用相应的Model部分逻辑,把产生的数据结果交给View部分,让View渲染出必要的输出

  MVC框架提出的数据流很理想,用户请求先到达Controller,由Controller调用Model获得数据,然后把数据交给View。但是,在实际框架实现中,总是允许View和Model直接通信

  然而,在MVC中让View和Model直接对话就是灾难

 

Flux

【优势】

  在Flux中,Store只有get方法,没有set方法,根本不可能直接去修改其内部状态,View只能通过get方法获取Store的状态,无法直接去修改状态,如果View想要修改Store的状态,只能派发一个action对象给Dispatcher

【不足】

  1、Store之间依赖关系

  在Flux的体系中,如果两个Store之间有逻辑依赖关系,就必须用上Dispatcher的waitFor函数

  2、难以进行服务器端渲染

  3、Store混杂了逻辑和状态

 

Redux

  Redux的含义是Reducer+Flux。Reducer是一个计算机科学中的通用概念。以Javascript为例,数组类型有reduce函数,接受的参数是一个reducer,reducer做的事情就是把数组所有元素依次做规约,对每个元素都调用一次参数reducer,通过reducer函数完成规约所有元素的功能

  Flux的基本原则是单向数据流,Redux在此基础上强调三个基本原则:

  1、唯一数据源

  2、保持状态只读

  3、数据改变只通过纯函数完成

 

Redux

  Redux的含义是Reducer+Flux。Reducer是一个计算机科学中的通用概念。以Javascript为例,数组类型有reduce函数,接受的参数是一个reducer,reducer做的事情就是把数组所有元素依次做规约,对每个元素都调用一次参数reducer,通过reducer函数完成规约所有元素的功能

  Flux的基本原则是单向数据流,Redux在此基础上强调三个基本原则:

  1、唯一数据源

  2、保持状态只读

  3、数据改变只通过纯函数完成

 

容器和展示

  一个React组件基本上要完成以下两个功能:

  1、读取Store的状态,用于初始化组件的状态,同时还要监听Store的状态改变;当Store状态发生变化时,需要更新组件状态,从而驱动组件重新渲染;当需要更新Store状态时,就要派发action对象

  2、根据当前props和state,渲染出用户界面

  让一个组件只专注做一件事。于是,按照这两个功能拆分成两个组件。这两个组件是父子组件的关系。业界对于这样的拆分有多种叫法,承担第一个任务的组件,也就是负责和redux打交道的组件,处于外层,被称为容器组件;只专业负责渲染界面的组件,处于内层,叫做展示组件

  展示组件,又称为傻瓜组件,就是一个纯函数,根据props产生结果。实际上,让展示组件无状态,只根据props来渲染结果,是拆分的主要目的之一。状态全部交给容器组件去处理

或者,直接使用解构赋值的方法 

React-redux

  react-redux遵循将组件分成展示组件和容器组件的规范。react-redux提供了两个功能:

  1、Provider组件,可以让容器组件默认可以取得state,而不用当容器组件层级很深时,一级级将state传下去

     2、connect方法,用于从展示组件生成容器组件。connect的意思就是将这两种组件连接起来

 

 

模块化应用

  从架构出发,开始一个新应用时,有几件事情是一定要考虑清楚的:

  1、代码文件的组织结构

  2、确定模块的边界

  3、Store的状态树设计

【代码文件的组织结构】

  Redux应用适合于按功能组织,也就是把完成同一应用功能的代码放在一个目录下,一个应用功能包含多个角色的代码。在Redux中,不同的角色就是reducer、actions和视图。而应用功能对应的就是用户界面上的交互模块

  以Todo应用为例,这个应用的两个基本功能就是TodoList和Filter,所以代码可以这样组织:

 

【模块接口】

  不同功能模块之间的依赖关系应该简单而清晰,也就是所谓的保持模块之间低耦合性;一个模块应该把自己的功能封装得很好,让外界不要太依赖于自己内部的结构,这样不会因为内部的变化而影响外部模块的功能,这就是所谓的高内聚性

【状态树的设计】

  状态树的设计需要遵循如下几个原则:

  1、一个模块控制一个状态节点

  2、避免冗余数据

  3、树形结构扁平  (避免依赖)

  对于Todo应用的状态树设计如下

 

reselect

  reselect库的原理是只要相关状态没有改变,那就直接使用上一次的缓存结果。reselect用来创造选择器,接收一个state作为参数的函数,返回的数据是某个mapStateToProps需要的结果

  首先,安装reselect库

    npm install --save reselect

  reselect提供了创造选择器的createSelector函数,这是一个高阶函数,也就是接受函数为参数来产生一个新函数的函数

  createSelector 接收一个 input-selectors 数组和一个转换函数作为参数。如果 state tree 的改变会引起 input-selector 值变化,那么 selector 会调用转换函数,传入 input-selectors 作为参数,并返回结果。如果 input-selectors 的值和前一次的一样,它将会直接返回前一次计算的数据,而不会再调用一次转换函数。

 

常见错误

  在使用redux的过程中,会出现如下的常见错误

【错误:reducers不能触发actions】

      Uncaught Error: Reducers may not dispatch actions.

一般来说,出现"Reducedrs may not dispatch actions"的错误,是因为reducer中出现路由跳转语句,而跳转到的语句正好发送了dispatch。从而,reducer不再是纯函数

 

【redux中的state发生变化,但页面没有重新渲染】

  一般地,是因为展开运算符使用不当所至

  对于对象的展开运算符,需要把...state放到第一个条目位置,因为后面的条目会覆盖展开的部分

      return {...item,completed:!item.completed}

 

【reducer中不能使用undefined】

  1、reducer中state不能返回undefined,可以用null代替

 

posted @ 2018-07-19 14:27  成长的Catfish  阅读(176)  评论(0编辑  收藏  举报