这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
React入门
历史与应用
React应用:
- 前端网页
- 移动端 React Native
- Electron
- React Three Fiber
发展历史:
React前身是FaxJS, React 的特性也是在不断加强FaxJS的特性
FaxJS特性:
- 支持客户端与服务端渲染
- 响应式
- 高性能
- 结构化
React设计思路
原生JS的痛点
-
状态更新, UI 需要自己手动调用DOM API 进行更改
-
代码层面无封装、隔离, 代码层面无组件化概念
-
UI 之间的数据依赖关系需要手动维护, 不能一个改变另外的可以跟着一块变, 依赖链路过长会遇到回调地狱
响应式与转换式
转换式系统
例子: 编译器
给定输入求解出输出
响应式系统
例子: UI 界面
监听事件, 消息驱动, 事件响应
graph LR
id1[事件发生] --> id2["执行回调 (响应事件)"] --> id3["状态变更 (可能是回调函数导致)"]
前端 UI:
graph LR
id1[事件发生] --> id2["执行回调 (响应事件)"] --> id3["状态变更 (可能是回调函数导致)"] --> id4[UI更新]
期望
-
状态更新, UI 也更新
-
代码可以语义化组件, 可复用, 可封装
-
状态之间的依赖关系不需要手动维护, 声明即可
例如:
A=B+C, 若B或C中任意一个变动,A就会自动赋值为B+C, 不需要手动计算
组件化准则
-
组件是组件的组合或者是原子组件
-
组件内有自己的状态, 外部不可见
-
父组件可以将状态传入到组件内部 (父组件应能控制子组件) (接口化)
组件化的设计
- 组件声明了状态与 UI 的映射 (输入几个状态返回一个 UI)
- 组件有 Props 和 State 两种状态
- 组件可以是其他组件拼装而成
省流: 组件内有自己的私有状态 (State) 并且能够接受外部的参数 (Props) 来提高复用性, 最后根据现有的 State 与 Props 返回一个 UI
React 生命周期
React Hooks 写法
Effect --- 副作用 useEffect()
组件内单纯执行类似于const a = b + c这种不会影响组件外部的语句
会给组件外部造成影响的
发起网络请求 (与外部系统交互)
操作sessionStorage或者localStorage等
纯函数, 1+2=3这种, 跟组件外无交互的
副作用函数:
()=>{
document.title = 'Title';
}
react 里如果需要使用副作用执行的, 需要使用useEffect(effectFunc)函数
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 在这段代码里, useEffect() 会在组件 Mount 时执行
// 对应上面生命周期的 Mounting - componentDidMount
// 也就是说只会执行一次
useEffect(()=>{
document.title = `你点击了 ${count} 次`;
});
return (
<div>
<p>你点击了 {count} 次!</p>
<button onClick={ ()=>setCount(count + 1) } >
点我
</button>
</div>
);
}
react 在组件 mount 时与依赖项被 set 时会执行 useEffect(func, depend) 的函数
Hooks
可以挂载到 react 组件生命周期上执行的函数
例如 useEffect, useState这种都是hooks
使用法则
不要再循环, 条件, 嵌套函数内使用 hooks
指令式&声明式&响应式
- 指令式 一步步告诉如何操作
- 声明式 发出指令自动干活
- 响应式 是声明式编程的类别, 不仅可以自动干活, 还可以根据状态自动去触发
React的实现
JSX不符合JS标准
将 JSX 转译为 JS
返回的JSX发生改变时如何更新DOM
使用虚拟DOM, 虚拟DOM是一种用于和真实DOM同步, 但是在JS内存中维护的一个对象, 具有和DOM类似的树状结构, 并和DOM建立一一对应的关系
可以告诉React UI的状态, 就能确保DOM匹配该状态, 从而从手动DOM, 事件处理中解放出来
更新DOM流程
diff
算法太差, 大部分略........
Heuristic O(n) Algorithm
两棵树从根开始递归比对, 三条规则:
- 不同类型的元素: 替换
- 同类型的DOM元素: 更新
- 同类型的组件元素: 递归
React状态管理
核心思想
将状态抽到 UI 外部进行统一管理
个人理解 Vue 的
Vuex与Pinia也一样的思想
缺点: 增强了组件与store的耦合
状态管理库推荐 (ps: 用哪个都可以, 除非特别大)
- Redux (讲师: 设计有些问题, 新的比它好?) 使用时可以去看看对应版本的评价
- xstate (基于状态机思想)
- mobx
- recoil
状态机思想
graph LR
id1[当前状态] --> id2[收到外部事件] --> id3[状态迁移或转换]
应用场景
整个App所拥有的放到Store里, 单独组件拥有的不放
Modern.js/Reduck
Modern.js 基于 React 的全栈开发框架, Reduck 是其内部的状态管理库
运用方式
省流, 和Pinia差不多, 参考代码如下:
// 定义 Model
import { model } from '@modern-js/runtime/model';
const countModel = model('count').define({
state: {
x: 0,
y: 0,
sum: 0,
},
actions: {
incrementX(state) {
state.x += 1;
},
incrementY(state) {
state.y += 1;
},
},
});
export default countModel;
// 使用 Model
import { useModel } from '@modern-js/runtime/model';
// [ <state>, <actions> ]
const [{x, y}, {incrementX, incrementY}] = useModel(countModel);
// 获取 state
console.log(x);
console.log(y);
// 调用 actions
incrementX()
incrementY()
应用级框架推荐
- Next.js
- Modern.js
- Blitz 无API思想的全栈开发框架, 开发过程无需写API与CURD逻辑, 适合前后端紧密结合的小团队项目