React初识 | 青训营笔记

97 阅读6分钟

React初识 | 青训营笔记

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

今天这节课收获挺大的,逐层渐进地了解了React的设计思路和基本实现方式,以及现代常见的基于React开发的工程化框架。

初识React

React:是Facebook开发的一款JS库。

“A javascript library for building user interfaces.”

React应用

  • 前端应用开发,如Facebook、Instagram、Netflix网页版
  • 移动原生应用开发,如Instagram,Discord,Oculus
  • 结合Electron,进行桌面应用开发

React设计思路

React设计思路01 —— UI编程的痛点(对症下药)

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

React设计思路02 —— 响应式与转换式

image.png

前端UI(采用响应式系统):

image.png

React设计与实现 —— 响应式编程

  1. 状态更新, UI自动更新
  1. 前端代码组件化, 可复用, 可封装
  1. 状态之间的互相依赖关系, 只需声明即可

React设计与实现01 —— 组件化

image.png

ps:

DOM不是JS的变量, DOM本身是浏览器内部维护的状态, 我们只能通过调用JS的DOM-API去修改DOM, 不可以去随意的修改它,

DOM和UI是一一对应的关系

总结:

  • 组件是组件的组合/原子组件
  • 组件内拥有状态, 外部不可见
  • 父组件可将状态传入组件内部

React的设计与实现02 —— 状态归属问题

上图中,当前价格 状态属于谁?

当前价格属于Root节点

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

即:当多个组件需要共享同一个数据时,这个数据存在的位置应该位于所有共享组件的父节点以上。

当前价格如何改变?

提示:在js中,函数是一等公民,也就是说可以将函数看作一个变量

image.png

将onChangeValue()向下传递

image.png

React是单向数据流, 还是双向数据流?)

React是单向数据流。

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

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

在状态管理库中实现

React的设计与实现03 —— 组件化

组件设计:

  • 组件声明了状态和UI的映射
  • 组件有Props/State两种状态
  • "组件"可以由其他组件拼装而成

组件代码会是什么样子?

  • 组件内部拥有私有状态State
  • 组件接受外部的Porps状态提供复用性
  • 根据当前的State/Props, 返回一个UI

React的设计与实现04 —— 生命周期

组件的生命周期可分成三个状态:

  • Mounting(挂载):已插入真实 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸载):已移出真实 DOM

image.png

这部分可以看一下菜鸟教程

React 组件生命周期 | 菜鸟教程 (runoob.com)

React(hooks)写法

useState

hooks写法不是直接修改变量,而是通过函数修改变量,实现控制

 import {useState} from 'react'
 const [count,setCount] = useState(0)
 //此时修改count就需要调用setCount函数
 setCount(count + 1)

hooks提供的工具

  1. useState ----> 相当于类组件中的 constructor 对数据做初始化
  2. useEffect----> 对数据进行挂载,更新。在useEffect的 return()=>{ } 中会执行卸载。
  3. useReducer()可以去了解一下,三个参数。一般可用useState()实现相同效果
  4. useMemo() 函数值返回依赖,值改变会重新计算。
  5. useRef 定一个不用渲染页面的值 const searchParmas = useRef(null)
  6. useContext 定义在父组件中,接收context对象,返回对象当前值,在父组件发生变化时,重新渲染子组件。
  7. 自定义hooks, 需要使用‘use’开头。

这部分可以看一下这篇文章

「React 进阶」 React 全部 Hooks 使用大全 (包含 React v18 版本 ) - 掘金 (juejin.cn)

React的实现

React的实现 —— Problems

  1. JSX不符合JS标准语法
  1. 返回的JSX发生改变时, 如何更新DOM
  1. State/Props更新时, 要重新触发render函数

1.JSX不符合JS标准语法

解决办法是:transpile(转义)

补充:compile和transpile的区别:

compile是编译, transpile是转义:把一个语法的语言转成另外一个语言(例如less转成css)

HTML本质上是一个树状结构, 每一个节点可以有自己的属性, 可以表示成JSON数据格式, 因此可以转义

2. 返回的JSX发生改变时, 如何更新DOM

真实DOM是浏览器内部维护的状态, 我们只能通过DOM接口去修改DOM, 而不能直接拿到DOM就随便更改

  • 指令式编程(面向过程)

    • 一步一步, 手动告诉程序怎么做
  • 声明式编程(面向对象)

    • 发出一个指令, 就把事情办完了;

    • 现在主流的前端框架都是声明式编程

    • 为什么不把声明式编程的方式植入浏览器中?

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

    • 是声明式编程的一种, 当一个事物状态改变时, 改变其他事物的状态
Virtual DOM (虚拟DOM)

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

它赋予了React声明式的API, 您告诉React希望让UI是什么状态, React就确保DOM匹配该状态. 使您可以从属性操作,事件处理和手动更新DOM这些在构建应用程序时必要的操作中解放出来

React弊病: 当父组件发生状态改变时, 它的所有子节点要全部更新 11 image.png

How to Diff?

完美的最小Diff算法, 需要O(n*3)的复杂度

权衡更新次数少和计算速度快的要求, 实际我们牺牲了理论最小Diff, 换取时间, 得到了O(n)复杂度的算法

即Heuristic O(n) Algorithm(启发式O(n)算法)

image.png

react状态管理库

React状态管理库将state(状态)抽离到组件外部,进行统一管理。

常见的状态管理库:reduxxstatemobxrecoil

image.png

状态机

当前状态,收到外部事件,迁移到下一个状态。

image.png

应用级框架科普

image.png

参考博客:

链接:juejin.cn/post/712904…,作者:Luminous