这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
React课程笔记(下)
一、重点内容
- React 的实现 - How to Diff
- 编程范式
- 数据Store
- 状态管理库
二、详细知识点
1、diff
- diffing过程是递归过程
- 父组件可以嵌套子组件,是一个树
- 当父组件的状态改变时,所有的子组件,包括子组件的子组件,递归的发生重新render,函数执行一遍(非DOM更新)
How to Diff?
- 完美的最小Diff算法【实质是树的增删改等】, 需要O(n*3)的复杂度
- 更新次数少和计算速度快之间需要平衡, 实际我们牺牲了理论最小Diff, 换取时间, 得到了O(n)复杂度的算法。
- 即Heuristic O(n) Algorithm(启发式O(n)算法)
启发式算法:算法本身的逻辑没有经过严格的证明,但从语义上或直觉上似乎是对的。
Diff实现
- 不同类型的元素:替换
- 同类型的DOM元素:更新
- 同类型的组件元素:递归
2、编程范式:指令式编程、声明式编程、响应式编程
- 指令式编程:手动告诉程序我要怎么做的全部步骤和内容
- 声明式编程:只需要告诉做什么,即发出一个指令,不需要告诉怎么做,不需要底层实现
- 响应式编程:是声明式编程的一种,不仅可以声明UI,又可以作出响应;当某个状态改变时,自动更改其他依赖状态,自动更新UI。是自己响应自己的一个过程。
思考:既然前端都是声明式编程,我们为什么不把声明式的能力直接植入到浏览器中?
浏览器作为应用平台, 不能提供更高层次的东西, 这样会把自由度降低
3、React是单向数据流, 还是双向数据流?
单向。 永远是父组件给子组件传东西(函数/变量), 而子组件不能给父组件传东西, 子组件不能改变父组件的状态, 子组件只能通过接受父组件传递过来的函数, 进而改变父组件的状态。
4、数据Store
- 每个UI组件都和数据Store交互,实现状态共享
- 某一个数据Store强耦合,应用级别,或 多组件需要共享的,才会放入Srore内部。
- 理解:将所有组件看做一个整体组件,Store是它的state状态
- 组件依赖于实际外部状态管理的Store,一般出现在实际的业务代码中(例如app会使用,但library不会这么用)
既然这样可以,为什么还要把状态放到组件内部?
最大的坏处:降低组件的复用性
5、React状态管理库推荐
- redux
- xstate
- mobx
- recoil
总的思想:将状态抽离到UI外部进行统一管理
6、状态应该放在哪里?
- 注意区分 被整个app所拥有的,还是被某个组件所拥有。
- 例如当前用户的头像或用户信息,放在Store,任何地方都可能用到,发起一次请求就可以了。
- 不希望每个组件在获得CurrentUser的时候都向后端发起一次请求,只希望在Store里面统一的在页面渲染的时候,发起一次请求,每一个组件读CurrentUser的时候都从Store里面读。
三、个人总结
-
React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。
-
React优点:
- 速度快:在UI渲染过程中,React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。
- 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
- 模块化:为你程序编写独立的模块化UI组件,这样当某个或某些组件出现问题是,可以方便地进行隔离。
- 单向数据流:Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。
- 同构、纯粹的javascript:因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
- 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。