React课程笔记(下) | 青训营笔记

80 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天

React课程笔记(下)

一、重点内容

  1. React 的实现 - How to Diff
  2. 编程范式
  3. 数据Store
  4. 状态管理库

二、详细知识点

1、diff

  • diffing过程是递归过程
  • 父组件可以嵌套子组件,是一个树
  • 当父组件的状态改变时,所有的子组件,包括子组件的子组件,递归的发生重新render,函数执行一遍(非DOM更新)

How to Diff?

  • 完美的最小Diff算法【实质是树的增删改等】, 需要O(n*3)的复杂度
  • 更新次数少和计算速度快之间需要平衡, 实际我们牺牲了理论最小Diff, 换取时间, 得到了O(n)复杂度的算法。
  • 即Heuristic O(n) Algorithm(启发式O(n)算法)

启发式算法:算法本身的逻辑没有经过严格的证明,但从语义上或直觉上似乎是对的。

Diff实现

  1. 不同类型的元素:替换
  2. 同类型的DOM元素:更新
  3. 同类型的组件元素:递归

2、编程范式:指令式编程、声明式编程、响应式编程

  • 指令式编程:手动告诉程序我要怎么做的全部步骤和内容
  • 声明式编程:只需要告诉做什么,即发出一个指令,不需要告诉怎么做,不需要底层实现
  • 响应式编程:是声明式编程的一种,不仅可以声明UI,又可以作出响应;当某个状态改变时,自动更改其他依赖状态,自动更新UI。是自己响应自己的一个过程。

思考:既然前端都是声明式编程,我们为什么不把声明式的能力直接植入到浏览器中?

 浏览器作为应用平台, 不能提供更高层次的东西, 这样会把自由度降低

3、React是单向数据流, 还是双向数据流?

单向。 永远是父组件给子组件传东西(函数/变量), 而子组件不能给父组件传东西, 子组件不能改变父组件的状态, 子组件只能通过接受父组件传递过来的函数, 进而改变父组件的状态。

4、数据Store

  • 每个UI组件都和数据Store交互,实现状态共享
  • 某一个数据Store强耦合,应用级别,或 多组件需要共享的,才会放入Srore内部。
  • 理解:将所有组件看做一个整体组件,Store是它的state状态
  • 组件依赖于实际外部状态管理的Store,一般出现在实际的业务代码中(例如app会使用,但library不会这么用)

既然这样可以,为什么还要把状态放到组件内部?

最大的坏处:降低组件的复用性

5、React状态管理库推荐

  1. redux
  2. xstate
  3. mobx
  4. recoil

总的思想:将状态抽离到UI外部进行统一管理

6、状态应该放在哪里?

  • 注意区分 被整个app所拥有的,还是被某个组件所拥有。
  • 例如当前用户的头像或用户信息,放在Store,任何地方都可能用到,发起一次请求就可以了。
  • 不希望每个组件在获得CurrentUser的时候都向后端发起一次请求,只希望在Store里面统一的在页面渲染的时候,发起一次请求,每一个组件读CurrentUser的时候都从Store里面读。

三、个人总结

  • React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。

  • React优点:

  1. 速度快:在UI渲染过程中,React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。
  2. 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
  3. 模块化:为你程序编写独立的模块化UI组件,这样当某个或某些组件出现问题是,可以方便地进行隔离。
  4. 单向数据流:Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。
  5. 同构、纯粹的javascript:因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
  6. 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。