React入门 | 青训营笔记

139 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的的第7天

历史与应用

  1. 2010年,FaceBook在其php生态中,引入了xhp框架,首次引入了组合式组件的思想,启发了后来的React的设计。

  2. Jordan Walke创造了FaxJS,也就是后来的React原型

    image.png

  3. 2012年,FaceBook收购Instagram后,该FaxJS项目在内部得到使用,Jordan Walke基于此经验,创造了React。

  4. 2013年,React正式开源,在2013JSConf上其介绍了这款框架。

  5. 2014年-今天:各种新工具/框架。

    image.png

设计思路

UI编程痛点

  1. 状态更新,UI不会自动更新,需要手动地调用DOM进行更新。
  2. 欠缺基本的代码层面的封装和隔离,代码层面没有组件化。
  3. UI之间的数据依赖关系,需要手动维护。如果依赖链路长,则会遇到callback hell。

响应式与转换式

  • 转换式系统:给定输入,求解输出

    • 编译器
    • 数值计算
  • 响应式系统:监听事件,消息驱动

    • 监控系统
    • UI 界面

响应式系统

image.png

前端 UI:

image.png

响应式编程

  1. 状态更新,UI自动更新。
  2. 前端代码组件化,可复用、可封装(避免出现屎山)。
  3. 状态之间互相依赖关系,只需要声明即可。

React 哲学

你可以自上而下或者自下而上构建应用:

自上而下意味着首先编写层级较高的组件,自下而上意味着从最基本的组件开始编写。

当你的应用比较简单时,使用自上而下的方式更方便;对于较为大型的项目来说,自下而上地构建,并同时为低层组件编写测试是更加简单的方式。

只保留应用所需的可变 state 的最小集合,其他数据均由它们计算产生

通过问自己以下三个问题,你可以逐个检查相应数据是否属于 state:

  1. 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
  2. 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
  3. 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。

组件化

组件化.png

  1. 组件是 组件的组合 / 原子组件。
  2. 组件内拥有状态,外部不可见。
  3. 父组件可以将状态传入组件内部。(让父组件能够控制子组件)

状态归属问题?

如果多个同级组件要共同管理一个状态,就会发生“状态上升”的情况。

状态上升:状态归属于两个节点向上寻找到的最近的祖宗节点。

当有大量状态上升到Root节点,就会导致状态管理混乱。此时需要引入全局状态管理的概念。

Q1:React是单向数据流,还是双向数据流?

单向数据流。 React仅支持父组件向子组件传值。

子组件想要修改父组件的值,需要父组件向子组件提供修改父组件本身属性的方法(函数在JS中是一等公民)

Q2:如何解决状态不合理上升的问题?

状态管理库。

Q3:组件的状态改变后,如何更新DOM?

Virtual DOM + Diff算法。

组件设计

  1. 组件声明了状态和UI的映射。
  2. 组件有Props / State 两种状态。
  3. 组件可由其他组件拼装而成。

生命周期

声明周期在纵向上分为三个状态:

  • Mounting
  • Updating
  • Unmounting

生命周期.png

hooks的写法

函数副作用

函数副作用是指函数在正常工作任务之外对外部环境所施加的影响。

具体地说,函数副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境。函数的副作用也有可能是发生在函数运行期间,由于对外部数据的改变,导致了同步运行的外部函数受到影响。

useEffect

传入一个函数和一个数组,数组是状态的数组,称为依赖项。该函数在mount、依赖项被set时执行。

有副作用的函数,要传进useEffect中执行。

不要在循环、条件或嵌套函数中调用Hooks。

源码实现

JSX不符合JS标准:转译

转译.png

返回的JSX改变时,如何更新DOM?

re-render.png

Virtual DOM(虚拟DOM)?

Virtual DOM是一种用于和真实DOM同步,而在JS内存中维护的一个对象,它具有和DOM类似的树状结构,并和DOM可以建立一一对应的关系。

不同编程范式

  • 指定式编程?(关注过程,C/C++)
  • 声明式编程?(函数式编程,关注要做的事)
  • 响应式编程?

State / Props更新时,要重新触发render函数

How to diff?

元素操作
不同类型的元素替换
同类型的DOM元素更新
同类型的组件元素递归

状态管理库

将状态抽离到UI外部进行统一管理。

何时使用:当前状态是否是整个App共同拥有的?

状态机

状态机.png

它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。

应用级框架科普

  1. Next.js:支持Unbundled Dev、SWC等,拥有Serverless一键部署

    nextjs.png

  2. Modern.js:全栈开发框架,内置许多开箱即用的工具。

    modernjs.png

    modernjs (2).png

  3. Blitz:无API思想的全栈开发框架,开发过程中无需写API调用和CRUD逻辑,适合前后端紧密结合的小团队项目。

课后问题

1. React 组件的 render 函数,在哪些时机下,会被重新执行?

组件中的state和props发生改变时。

2. React这种函数式编程,和 vue这种基于模版语法的前端框架,各有什么优点和缺点?

Vue.js

  • 性能好:使用官方提供的模板语法的组件不需要考虑性能优化。
  • 适应性:代码结构类似HTML、CSS、JS,无障碍迁移。
  • 灵活度低:相比React函数式的写法,灵活度不足。

React.js

  • 需要手动优化性能,对初学者不友好。
  • 灵活度高:依靠jsx这种函数式写法,能够使页面的编写像写js代码一样灵活。
  • 学习成本低:这里的成本指的是不需要记忆vue的那些模板写法(例如v-if、v-for等)。

3. React 推荐使用组合来进行组件的复用,而不是继承,背后有什么样的考虑?

因为本人并未使用过Rect,对于此没有深刻概念。知乎对此问题珠玉在前,在此贴出链接,仅供参考:

为什么 React 推崇 HOC 和组合的方式,而不是继承的方式来扩展组件? - 知乎 (zhihu.com)