这是我参与「第四届青训营」笔记创作活动的第8天
React设计思路
- UI编程痛点
- 更新状态之后还要手动通过DOM更新关联的各个控件,比较混乱
- 欠缺基本的代码层面的封装和隔离,代码层面没有组件化
- UI之间的数据依赖关系需要手动维护,如果依赖链路长容易遇到回调地狱
- 响应式与转换式
- 转换式:给定输入求解输出
- 编译器:输入文本,输出二进制文件
- 响应式:监听事件,消息驱动
- 人:接收到水烧开的信号,执行倒水操作
- 事件 -> 执行既定的回调 -> 状态变更 -> UI更新
- 转换式:给定输入求解输出
- 响应式UI编程
- 状态更新时UI自动更新
- 前端代码组件化,可复用、可封装
- 组件可以是组件的组合
- 组件声明了状态和UI的映射
- 组件内拥有外部不可见的状态State,接受外部状态Props从而提供复用性
- 父组件可将状态转入组件内部
- 只需声明状态之间的依赖关系即可自动维护
- 状态归属问题
- 存放: 两个组件共享的状态放在它们的公共祖先节点(状态上升)
- 改变: 将
onChangeValue函数向下传递到子节点 - React是单向数据流,只能从父组件传递到子组件
- 生命周期
- Mounting
- Updating
- Unmounting
React (Hooks) 写法
- 示例
import React, { useState, useEffect } from 'react'
function Example00(){
// useState添加状态,传入状态的初始值,返回两个值
// 第一个是状态引用count,第二个是改变状态的函数setCount
const [count, setCount] = useState(0)
// useEffect添加副作用,内部状态的更新对外部产生影响
// 在Mounting和Updating时执行
useEffect( () => {
document.title = `${count}`
})
return (
<div>
<button onClick={() => setCount(count + 1)}>
{count}
</button>
</div>
)
}
React实现
- JSX不符合JavaScript的语法,如何转换
- 直接转译(trans·pile),把返回的JSX转换成React的声明式API
- 返回的JSX发生改变时,如何更新DOM
- 只更新发生变化的部分(diff)以求性能优化
- diff算法:用较优解换取时间,选取时间复杂度O(n)的启发式算法(Heuristic Algorithm)
- 从上往下递归处理:
- 替换不同类型的元素
- 更新同类型的DOM元素
- 递归处理同类型的组件元素
- 从上往下递归处理:
- diff算法:用较优解换取时间,选取时间复杂度O(n)的启发式算法(Heuristic Algorithm)
- 在内存中维护一个虚拟DOM,与返回的JSX对应,和DOM一一对应
- 只更新发生变化的部分(diff)以求性能优化
State/Props更新时,如何触发render函数重新渲染
React状态管理库
如果把全局状态都放到根节点,每次更新都需要重新渲染整个页面,可以将状态抽离到UI外部进行统一管理。
- 推荐
- redux
- xstate
- mobx
- recoil
- 状态机
- Modern.js + Reduck
- Modern.js 字节发布的基于React的全栈开发框架
- Reduck 状态管理库
- 使用
useModel由外部的同一个模型管理共享状态
应用级框架科普
- NEXT.JS
- 硅谷明星公司Vercel开发的React框架
- 支持
Unbundled DevSWC等
- Modern.JS
- 字节跳动开发的全栈框架
- 内置最佳实践
- Blitz
- 无API思想的全栈开发框架
- 无需写API调用和CRUD逻辑