React特点
- 声明式
- 组件化
- 跨平台编写
React哲学(Thinking In React)
React 是用JavaScript构建快速响应的大型Web应用程序的首选方式之一。它在 Facebook和Instagram 上表现优秀。
等待资源加载时间和大部分情况下浏览器单线程执行是影响web性能的两大主要原因。
更新流程
Scheduler(调度器)
- 维护时间切片(类似requestldleCallback)
- 与浏览器任务调度
- 优先级调度
Reconciler(协调器)
- 将JSX转化为Fiber
- Fiber树对比(双缓存)
- 确定本次更新的 Fiber
Renderer(渲染器)
- 渲染器用于管理一棵 React 树,使其根据底层平台进行不同的调用。
总结_优缺点
优点
- 快速响应:Fiber
- 组件化:复用性强
- 声明式编程
- 跨平台:只需修改渲染器
缺点
- 大型应用需要配套学习状态管理、路由工具
- 不适合小型应用,需要用babel处理
React开发web应用
React Web 应用
架构
打包配置:JSX -> babel -> Js加载优化和错误降级。
路由
React Router向应用中快速地添加视图和数据流,保持页面与URL间的同步。
UI
可复用UI>组件->页面。可复用逻辑抽离成hook。
状态
多页面多组件共享信息redux & context
React组件
数据
通过定义state操作视图
Mount时获取数据更新stàte
Ref 保存与视图无直接关系的值
unMount前清空Ref
通信
props父子组件通信
context &redu×组件信息共享
UI
数据决定视图
通过Ref 获取到DOM
性能
函数使用useCallback
值或者计算使用useMemo
组件包裹memo
组件
Class组件
- 继承+构造函数
- this
- 生命周期
- render方法
函数式组件
- 没有生命周期
- 借助Hook
- return JSX
函数式相较于Class的优点
- 代码量骤减,组件干净清爽。
- 没有复杂的生命周期。
- 支持自定义hook,逻辑复用方便。
组件和Hook的关系
- 我们将UI拆成多个独立单元,这些单元组合可以构 成多种视图展示,这些独立单元就是组件。组件相当于原子。
- hook贴近组件内部运行的各种概念逻辑,effect. state、context等。hooks更贴切于电子。
Hook规则&原理
只能在最顶层使用Hook
React怎么知道哪个state对应哪个useState?
答案是React靠的是Hook调用的顺序
function Form( ) {
const [name,setName] = useState( 'Mary ' ); //1
const firstRender = useRef(true); // 2
if (firstRender.current) {
firstRender.current = false;
useEffect(function persistForm() { //3
localStorage.setItem('formData', name);
});
}
const [surname,setSurname] = useState( 'Poppins' ); //4
useEffect(function updateTitle() { //5
document.title = name + ' ' + surname;
});
// ...
}
useEffect(function persistForm() {
if (firstRender.current) {
localStorage.setItem( 'formData', name);
firstRender.current =,false;
}
});
只能在 React函数中调用Hook
- 在React函数组件中或
- 自定义Hook中调用自定义 Hook 必须以use开头
- Hook中的state是完全隔离的
Hook过期闭包问题
在JS中,函数运行的上下文是由定义的位置决定的,当函数的闭包包住了旧的变量值时,就出现了过期闭包问题。
function createIncrement(i) {
let value = 0;
function increment() {
value += i;
console.log( `Increment value is ${value}` );
const message = 'LogValue is ${value} `;
function logMessage() {
console.log(message)
};
return logMessage;
}
return increment;
}
const inc = createIncrement(1);
const log = inc(); //Increment value is ? 1
inc(); // Increment value is ? 2
inc(); // Increment value is ? 3
log(); // LogValue is ? 1
function WatchCount( ) {
const [count,setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
console.log( `current Count is ${count}`);
},1000);
return () => clearInterval(id);
},[]);
const increment = () => setCount( count + 1);
return (
<div>
{count}
<Button onClick={increment}>Increment</Button></div>
);
}