首页 男生 其他 深入浅出React和Redux

5.3.2 范式化状态树

深入浅出React和Redux 程墨 3015 2021-04-06 02:29

  您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!

  

  5.3.2 范式化状态树

  在第4章中已经介绍过,Redux Store的状态树应该设计的尽量扁平,在使用了reselect之后,我们可以进一步认为,状态树的设计应该尽量范式化(Normalized)。

  所谓范式化,就是遵照关系型数据库的设计原则,减少冗余数据。如果读者做过关系型数据库(比如MySQL或者PostgreSQL)的表设计,就知道范式化的数据结构设计就是要让一份数据只存储一份,数据冗余造成的后果就是难以保证数据一致性。

  与范式化相对,还存在“反范式化”的数据库设计,这在风生水起的NoSQL领域是一个惯常的设计风格。反范式化是利用数据冗余来换取读写效率,因为关系型数据库的强项虽然是保持一致,但是应用需要的数据形式往往是多个表join之后的结果,而join的过程往往耗时而且在分布式系统中难以应用。

  介绍范式化或者反范式化的数据库设计不是本书讨论范围内,这里只是用数据库的两种设计理念来类比Redux Store状态树的设计策略。

  假设我们给Todo应用做一个更大的改进,增加一个Type的概念,可以把某个TodoItem归为某一个Type,而且一个Type有特有的名称和颜色信息,在界面上,用户可以看到TodoItem显示为自己所属Type对应的颜色,TodoItem和Type当然是多对多的关系。

  用哪种方式设计状态树合适呢?更具体一点,如何设计代表TodoItem的状态树结构?

  如果使用反范式化的设计,那么状态树上的数据最好是能够不用计算拿来就能用,在Redux Store状态树的todos字段保存的是所有待办事项数据的数组,对于每个数组元素,反范式化的设计会是类似下面的对象:

  {

  id: 1, //待办事项id

  text: "待办事项1", //待办事项文字内容

  completed: false, //是否已完成

  type: { // 种类

  name: "紧急", //种类的名称

  color: "red" //种类的显示颜色

  }

  }

  在原有TodoItem对应状态中增加了type字段,包含name和color两个数据。当然,如果要达到数据扁平化的目的,应该是增加两个字段,分别为typeName和typeColor。

  这种状态设计的好处就是在渲染TodoItem组件时,从Redux Store上获得的状态可以直接使用name和color数据。但这也有缺点,当需要改变某种类型的名称和颜色时,不得不遍历所有TodoItem数据来完成改变。反范式化数据结构的特点就是读取容易,修改比较麻烦。

  如果使用范式化的数据结构设计,那么Redux Store上代表TodoItem的一条数据是类似下面的对象:

  {

  id: 1, //待办事项id

  text: "待办事项1", //待办事项文字内容

  completed: false, //是否已完成

  typeId: 1 //待办事项所属的种类id

  }

  用一个typeId代表类型,然后在Redux Store上和todos平级的根节点位置创建一个types字段,内容是一个数组,每个数组元素代表一个类型,一个种类的数据是类似下面的对象:

  {

  id: 1, //种类id

  name: "紧急", //种类的名称

  color: "red" //种类的显示颜色

  }

  当TodoItem组件要渲染内容时,从Redux Store状态树的todos字段下获取的数据是不够的,因为只有typeId。为了获得对应的种类名称和颜色,需要做一个类似关系型数据库的join操作,到状态树的types字段下去寻找对应typeId的种类数据。

  这个过程当然要花费一些时间,但是当要改变某个种类的名称或者颜色时,就异常地简单,只需要修改types中的一处数据就可以了。

  对比反范式方式和范式方式的优劣,不难看出范式方式更合理。因为虽然join数据需要花费计算时间,但是应用了reselect之后,大部分情况下都会命中缓存,实际上也就没有花费很多计算时间了。 深入浅出React和Redux

目录
设置
手机
书架
书页
评论