响应式系统与React | 青训营笔记

148 阅读3分钟

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

React设计思路

  • UI编程痛点
    • 更新状态之后还要手动通过DOM更新关联的各个控件,比较混乱
    • 欠缺基本的代码层面的封装和隔离,代码层面没有组件化
    • UI之间的数据依赖关系需要手动维护,如果依赖链路长容易遇到回调地狱
  • 响应式与转换式
    • 转换式:给定输入求解输出
      • 编译器:输入文本,输出二进制文件
    • 响应式:监听事件,消息驱动
      • 人:接收到水烧开的信号,执行倒水操作
      • 事件 -> 执行既定的回调 -> 状态变更 -> UI更新
  • 响应式UI编程
    • 状态更新时UI自动更新
    • 前端代码组件化,可复用、可封装
      • 组件可以是组件的组合
      • 组件声明了状态和UI的映射
      • 组件内拥有外部不可见的状态State,接受外部状态Props从而提供复用性
      • 父组件可将状态转入组件内部
    • 只需声明状态之间的依赖关系即可自动维护
  • 状态归属问题
    • 存放: 两个组件共享的状态放在它们的公共祖先节点(状态上升)
    • 改变: 将onChangeValue函数向下传递到子节点
    • React是单向数据流,只能从父组件传递到子组件
  • 生命周期
    • Mounting
    • Updating
    • Unmounting React lifecycle

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元素
          • 递归处理同类型的组件元素
    • 在内存中维护一个虚拟DOM,与返回的JSX对应,和DOM一一对应
  • State/Props更新时,如何触发render函数重新渲染

React状态管理库

如果把全局状态都放到根节点,每次更新都需要重新渲染整个页面,可以将状态抽离到UI外部进行统一管理

  • 推荐
    • redux
    • xstate
    • mobx
    • recoil
  • 状态机
  • Modern.js + Reduck
    • Modern.js 字节发布的基于React的全栈开发框架
    • Reduck 状态管理库
    • 使用useModel由外部的同一个模型管理共享状态

应用级框架科普

  • NEXT.JS
    • 硅谷明星公司Vercel开发的React框架
    • 支持Unbundled Dev SWC
  • Modern.JS
    • 字节跳动开发的全栈框架
    • 内置最佳实践
  • Blitz
    • 无API思想的全栈开发框架
    • 无需写API调用和CRUD逻辑