六十天前端强化训练之第十七天React Hooks 入门:useState 深度解析

=====欢迎来到编程星辰海的博客讲解======

看完可以给一个免费的三连吗,谢谢大佬!

目录

一、知识讲解

1. Hooks 是什么?

2. useState 的作用

3. 基本语法解析

4. 工作原理

5. 参数详解

a) 初始值设置方式

b) 更新函数特性

6. 注意事项

7. 类组件对比

8. 常见问题解答

二、核心代码示例

三、实现效果

四、学习要点总结

五、扩展阅读推荐

官方文档

优质文章

推荐学习路径

进阶资源

六、实践步骤

一、表单输入控制

二、动态列表组件

三、购物车组件(复杂状态)

四、自定义Hook:useCart

推荐练习项目:


一、知识讲解

1. Hooks 是什么?

React Hooks 是 React 16.8 引入的革命性特性,它允许开发者在函数组件中使用状态(state)和其他 React 特性。Hooks 的诞生解决了以下问题:

  • 类组件中生命周期函数带来的逻辑分散
  • 高阶组件带来的嵌套地狱(Wrapper Hell)
  • 函数组件无法使用状态的局限
  • 状态逻辑难以复用的问题

2. useState 的作用

useState 是最基础且重要的 Hook,它让函数组件具备管理局部状态的能力。其核心功能包括:

  • 声明组件内部状态
  • 提供状态更新方法
  • 触发组件重新渲染
  • 保持状态在多次渲染间的持久性

3. 基本语法解析

JAVASCRIPT

const [state, setState] = useState(initialState);

  • initialState:状态的初始值,可以是任何数据类型
  • state:当前状态值
  • setState:用于更新状态的函数

4. 工作原理

  • 初始化阶段:组件首次渲染时,useState 会读取初始值并保存
  • 更新阶段:调用 setState 后:
    1. 将新值加入更新队列
    2. 触发组件重新渲染
    3. 在下次渲染时返回更新后的状态
  • 渲染机制:每次渲染都有独立的状态快照(闭包特性)

5. 参数详解

a) 初始值设置方式

JAVASCRIPT

// 直接值初始化
const [count, setCount] = useState(0);// 函数式初始化(惰性初始化)
const [count, setCount] = useState(() => {const initialValue = calculateExpensiveValue();return initialValue;
});
b) 更新函数特性
  • 支持直接赋值更新:

    JAVASCRIPT

    setCount(5);
    
  • 支持函数式更新(推荐用于依赖前值的场景):

    JAVASCRIPT

    setCount(prevCount => prevCount + 1);
    

6. 注意事项

  • 异步更新:状态更新是异步的,不能立即获取到新值
  • 合并更新:React 会自动合并多个 setState 调用
  • 性能优化:使用函数式更新避免闭包陷阱
  • 不可变原则:始终返回新值而不是修改原值

7. 类组件对比

特性类组件函数组件 + useState
状态初始化constructoruseState 参数
状态更新方式this.setState()setState 函数
状态访问this.state直接使用状态变量
生命周期依赖需要无需
代码组织分散在各个生命周期方法中逻辑集中

8. 常见问题解答

Q:useState 和类组件的 state 有何不同?
A:useState 不会自动合并对象类型的状态,需要手动合并

Q:为什么 setCount(count + 1) 在异步操作中不可靠?
A:由于闭包特性,异步回调中的 count 可能不是最新值,应该使用函数式更新

Q:可以在条件语句中使用 useState 吗?
A:不行,所有 Hooks 都必须保证每次渲染的调用顺序一致

Q:如何存储复杂对象?

JAVASCRIPT

const [user, setUser] = useState({name: 'John',age: 25,address: {city: 'New York',zip: '10001'}
});// 正确更新方式
setUser(prev => ({...prev,age: 26,address: {...prev.address,zip: '10002'}
}));

二、核心代码示例

JSX

import React, { useState } from 'react';function Counter() {// 声明状态变量 count 及其更新函数 setCount// 初始值设为 0const [count, setCount] = useState(0);// 定义增加计数器的方法const increment = () => {// 使用函数式更新确保基于最新状态值setCount(prevCount => prevCount + 1);};// 定义减少计数器的方法const decrement = () => {setCount(prevCount => prevCount - 1);};// 定义重置计数器的方法const reset = () => {setCount(0);};return (<div style={styles.container}><h2>当前计数: {count}</h2><div style={styles.buttonGroup}>{/* 绑定点击事件 */}<button style={styles.button} onClick={increment}>+</button><button style={styles.button} onClick={decrement}>-</button><button style={styles.button} onClick={reset}>重置</button></div>{/* 条件渲染提示信息 */}{count >= 10 && <p style={styles.tip}>计数已经超过10啦!</p>}</div>);
}// 样式对象
const styles = {container: {textAlign: 'center',padding: '2rem',backgroundColor: '#f0f0f0',borderRadius: '8px',maxWidth: '400px',margin: '2rem auto'},buttonGroup: {display: 'flex',justifyContent: 'center',gap: '1rem',marginTop: '1rem'},button: {padding: '0.5rem 1rem',fontSize: '1.2rem',cursor: 'pointer',backgroundColor: '#2196f3',color: 'white',border: 'none',borderRadius: '4px',transition: 'background-color 0.3s'},tip: {color: '#d32f2f',marginTop: '1rem',fontWeight: 'bold'}
};export default Counter;

三、实现效果

计数器组件包含:

  1. 显示当前数值的标题
  2. "+"、"-" 和 "重置" 三个操作按钮
  3. 当数值 >=10 时显示提示信息
  4. 按钮悬停时的颜色变化效果
  5. 整洁的卡片式布局

四、学习要点总结

  1. 基础概念

    • useState 是用于给函数组件添加状态管理的 Hook
    • 遵循 const [state, setState] = useState(initialValue) 语法
  2. 使用规则

    • 只在组件的顶层调用 Hooks
    • 不要在循环、条件或嵌套函数中调用 Hooks
    • 遵循不可变原则(immutability)
  3. 最佳实践

    • 对于复杂对象,使用扩展运算符进行合并更新
    • 异步操作时使用函数式更新确保获取最新状态
    • 拆分多个 useState 管理不同状态
  4. 性能优化

    • 对于昂贵的初始化,使用函数式初始化
    • 当更新依赖前值时,必须使用函数式更新
    • 使用 React.memo 防止不必要的重新渲染
  5. 常见错误

    • 直接修改状态对象

    JAVASCRIPT

    // 错误示例
    const [user, setUser] = useState({name: 'John'});
    user.name = 'Mike'; // 直接修改原对象
    setUser(user);      // 不会触发更新// 正确做法
    setUser({...user, name: 'Mike'});
    
  • 在渲染函数中执行副作用操作
  • 忽视异步更新的特性

五、扩展阅读推荐

官方文档

  1. Hooks 简介
  2. useState API 文档
  3. Hooks 常见问题

优质文章

  1. useState 完全指南
  2. Hooks 原理剖析
  3. 函数式更新深入解析
  4. Hooks 最佳实践
  5. Hooks 与类组件对比

推荐学习路径

  1. 掌握 useState → useEffect → useContext 基础三件套
  2. 学习自定义 Hook 实现逻辑复用
  3. 了解 useReducer 管理复杂状态
  4. 学习性能优化相关 Hooks(useMemo/useCallback)
  5. 探索第三方 Hooks 库(如 ahooks)

进阶资源

  1. React Hooks 完全指南(免费电子书)
  2. Hooks 实现原理视频解析
  3. Hooks 测试策略

六、实践步骤

可以以下步骤进行实践:

  1. 从简单计数器开始
  2. 实现表单输入控制
  3. 创建动态列表组件
  4. 开发带有复杂状态的购物车
  5. 尝试将业务逻辑抽象为自定义 Hooks

一、表单输入控制

JSX

import React, { useState } from 'react';function UserForm() {// 使用单个对象管理所有表单字段const [formData, setFormData] = useState({username: '',email: '',password: '',newsletter: false});// 统一处理输入变化const handleInputChange = (e) => {const { name, value, type, checked } = e.target;setFormData(prev => ({...prev,[name]: type === 'checkbox' ? checked : value}));};// 处理表单提交const handleSubmit = (e) => {e.preventDefault();console.log('表单提交数据:', formData);alert(JSON.stringify(formData, null, 2));};return (<form style={formStyles} onSubmit={handleSubmit}><div style={inputGroup}><label>用户名:</label><inputtype="text"name="username"value={formData.username}onChange={handleInputChange}/></div><div style={inputGroup}><label>邮箱:</label><inputtype="email"name="email"value={formData.email}onChange={handleInputChange}/></div><div style={inputGroup}><label>密码:</label><inputtype="password"name="password"value={formData.password}onChange={handleInputChange}/></div><div style={checkboxGroup}><label><inputtype="checkbox"name="newsletter"checked={formData.newsletter}onChange={handleInputChange}/>订阅新闻邮件</label></div><button type="submit" style={submitButton}>提交</button></form>);
}// 样式配置
const formStyles = {maxWidth: '400px',margin: '2rem auto',padding: '2rem',backgroundColor: '#f8f9fa',borderRadius: '8px'
};const inputGroup = {marginBottom: '1rem'
};const checkboxGroup = {margin: '1rem 0'
};const submitButton = {backgroundColor: '#28a745',color: 'white',padding: '0.5rem 1rem',border: 'none',borderRadius: '4px',cursor: 'pointer'
};export default UserForm;

学习要点:

  1. 使用对象统一管理表单状态
  2. 处理多种输入类型(文本/复选框)
  3. 动态属性名更新技巧([name]: value)
  4. 表单提交时访问最新状态

二、动态列表组件

JSX

import React, { useState } from 'react';function TodoList() {const [todos, setTodos] = useState([{ id: 1, text: '学习React Hooks', completed: false },{ id: 2, text: '练习useState', completed: true }]);const [newTodo, setNewTodo] = useState('');// 添加新待办事项const addTodo = () => {if (newTodo.trim()) {setTodos([...todos, {id: Date.now(),text: newTodo,completed: false}]);setNewTodo('');}};// 切换完成状态const toggleTodo = (id) => {setTodos(todos.map(todo =>todo.id === id ? { ...todo, completed: !todo.completed } : todo));};// 删除待办事项const deleteTodo = (id) => {setTodos(todos.filter(todo => todo.id !== id));};return (<div style={container}><h2>待办事项列表 ({todos.length})</h2><div style={inputGroup}><inputtype="text"value={newTodo}onChange={(e) => setNewTodo(e.target.value)}placeholder="输入新事项"style={inputStyle}/><button onClick={addTodo} style={addButton}>添加</button></div><ul style={listStyle}>{todos.map(todo => (<li key={todo.id} style={itemStyle(todo.completed)}><inputtype="checkbox"checked={todo.completed}onChange={() => toggleTodo(todo.id)}/><span style={{ flex: 1 }}>{todo.text}</span><button onClick={() => deleteTodo(todo.id)}style={deleteButton}>删除</button></li>))}</ul></div>);
}// 样式配置
const container = {maxWidth: '600px',margin: '2rem auto',padding: '1rem'
};const inputGroup = {display: 'flex',gap: '0.5rem',marginBottom: '1rem'
};const inputStyle = {flex: 1,padding: '0.5rem'
};const addButton = {backgroundColor: '#17a2b8',color: 'white',border: 'none',padding: '0.5rem 1rem',borderRadius: '4px',cursor: 'pointer'
};const listStyle = {listStyle: 'none',padding: 0
};const itemStyle = (completed) => ({display: 'flex',alignItems: 'center',padding: '0.5rem',margin: '0.5rem 0',backgroundColor: completed ? '#d4edda' : '#fff',border: '1px solid #ddd',borderRadius: '4px',opacity: completed ? 0.7 : 1
});const deleteButton = {backgroundColor: '#dc3545',color: 'white',border: 'none',padding: '0.25rem 0.5rem',borderRadius: '4px',cursor: 'pointer'
};export default TodoList;

学习要点:

  1. 使用数组管理动态列表
  2. 列表项的增删改操作
  3. 正确使用key属性
  4. 复杂状态对象的更新方法
  5. 条件样式渲染技巧

三、购物车组件(复杂状态)

JSX

import React, { useState } from 'react';const initialProducts = [{ id: 1, name: '商品A', price: 100, quantity: 1 },{ id: 2, name: '商品B', price: 200, quantity: 2 }
];function ShoppingCart() {const [cart, setCart] = useState(initialProducts);const [newProduct, setNewProduct] = useState('');// 计算总价const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);// 添加新商品const addProduct = () => {if (newProduct.trim()) {setCart([...cart, {id: Date.now(),name: newProduct,price: Math.floor(Math.random() * 500) + 100,quantity: 1}]);setNewProduct('');}};// 更新商品数量const updateQuantity = (id, delta) => {setCart(cart.map(item => {if (item.id === id) {const newQuantity = Math.max(1, item.quantity + delta);return { ...item, quantity: newQuantity };}return item;}));};// 移除商品const removeProduct = (id) => {setCart(cart.filter(item => item.id !== id));};return (<div style={container}><h2>购物车 (总价: ¥{total})</h2><div style={inputGroup}><inputtype="text"value={newProduct}onChange={(e) => setNewProduct(e.target.value)}placeholder="输入商品名称"style={inputStyle}/><button onClick={addProduct} style={addButton}>添加商品</button></div><ul style={listStyle}>{cart.map(item => (<li key={item.id} style={itemStyle}><div style={itemInfo}><span style={itemName}>{item.name}</span><span>单价: ¥{item.price}</span></div><div style={quantityControls}><button onClick={() => updateQuantity(item.id, -1)}style={controlButton}>-</button><span style={quantityDisplay}>{item.quantity}</span><button onClick={() => updateQuantity(item.id, 1)}style={controlButton}>+</button></div><div style={itemSubtotal}>小计: ¥{item.price * item.quantity}<buttononClick={() => removeProduct(item.id)}style={removeButton}>删除</button></div></li>))}</ul></div>);
}// 样式配置
const container = {maxWidth: '800px',margin: '2rem auto',padding: '1rem'
};const inputGroup = {display: 'flex',gap: '0.5rem',marginBottom: '1rem'
};const inputStyle = {flex: 1,padding: '0.5rem'
};const addButton = {backgroundColor: '#007bff',color: 'white',border: 'none',padding: '0.5rem 1rem',borderRadius: '4px',cursor: 'pointer'
};const listStyle = {listStyle: 'none',padding: 0
};const itemStyle = {display: 'flex',justifyContent: 'space-between',alignItems: 'center',padding: '1rem',margin: '0.5rem 0',backgroundColor: '#fff',border: '1px solid #ddd',borderRadius: '4px'
};const itemInfo = {flex: 2,display: 'flex',flexDirection: 'column',gap: '0.5rem'
};const itemName = {fontWeight: 'bold'
};const quantityControls = {display: 'flex',alignItems: 'center',gap: '0.5rem'
};const controlButton = {padding: '0.25rem 0.5rem',minWidth: '32px',backgroundColor: '#6c757d',color: 'white',border: 'none',borderRadius: '4px',cursor: 'pointer'
};const quantityDisplay = {minWidth: '30px',textAlign: 'center'
};const itemSubtotal = {flex: 1,display: 'flex',flexDirection: 'column',alignItems: 'flex-end',gap: '0.5rem'
};const removeButton = {backgroundColor: '#dc3545',color: 'white',border: 'none',padding: '0.25rem 0.5rem',borderRadius: '4px',cursor: 'pointer'
};export default ShoppingCart;

学习要点:

  1. 多层嵌套状态的管理
  2. 复杂状态更新模式
  3. 派生状态(总价)的计算
  4. 不可变数据更新模式
  5. 复杂组件的样式组织

四、自定义Hook:useCart

JSX

// useCart.js
import { useState } from 'react';function useCart(initialItems = []) {const [cart, setCart] = useState(initialItems);const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);const addItem = (newItem) => {setCart([...cart, {...newItem,id: Date.now(),quantity: 1}]);};const updateQuantity = (itemId, delta) => {setCart(currentCart =>currentCart.map(item =>item.id === itemId? { ...item, quantity: Math.max(1, item.quantity + delta) }: item));};const removeItem = (itemId) => {setCart(currentCart => currentCart.filter(item => item.id !== itemId));};return {cart,total,addItem,updateQuantity,removeItem};
}export default useCart;// 使用示例
function CartComponent() {const { cart, total, addItem, updateQuantity, removeItem } = useCart();// ...组件实现与前面购物车示例类似
}

学习要点:

  1. 自定义Hook的命名规范(必须用use开头)
  2. 状态逻辑的封装
  3. Hook之间的通信
  4. 返回可操作的方法集
  5. 实现业务逻辑复用

推荐练习项目:

  • 个人博客系统
  • 任务管理系统(类似Trello)
  • 电子商务平台
  • 实时数据监控仪表盘

学完后建议弄清以下问题:

  1. 状态更新的原理是什么?
  2. 如何避免不必要的重新渲染?
  3. 复杂状态如何组织更合理?
  4. 如何调试状态变化?
  5. 如何测试Hook相关逻辑?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/897913.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IEC61850标准下MMS 缓存报告控制块 ResvTms详细解析

IEC61850标准是电力系统自动化领域唯一的全球通用标准。IEC61850通过标准的实现&#xff0c;使得智能变电站的工程实施变得规范、统一和透明&#xff0c;这大大提高了变电站自动化系统的技术水平和安全稳定运行水平。 在 IEC61850 标准体系中&#xff0c;ResvTms&#xff08;r…

【JVM】GC 常见问题

GC 常见问题 哪些情况新生代会进入老年代 新生代 GC 后幸存区&#xff08;survivor&#xff09;不够存放存活下来的对象&#xff0c;会通过内存担保机制晋升到老年代。大对象直接进入老年代&#xff0c;因为大对象再新生代之间来会复制会影响 GC 性能。由 -XX:PretenureSizeT…

Audacity 技术浅析(一)

Audacity 是一个开源的音频编辑工具&#xff0c;虽然它主要用于音频编辑和处理&#xff0c;但也可以通过一些插件和功能实现基本的音频生成功能。 1. Audacity 的音频生成基础 Audacity 的音频生成主要依赖于其内置的生成器、效果器以及 Nyquist 编程语言。这些工具允许用户创…

G-Star 公益行起航,挥动开源技术点亮公益!

公益组织&#xff0c;一直是社会温暖的传递者&#xff0c;但在数字化浪潮中&#xff0c;也面临着诸多比大众想象中复杂的挑战&#xff1a;项目管理如何更高效&#xff1f;志愿者管理又该如何创新&#xff1f;宣传推广怎么才能更有影响力&#xff1f;内部管理和技术支持又该如何…

MongoDB 数据导出与导入实战指南(附完整命令)

1. 场景说明 在 MongoDB 运维中&#xff0c;数据备份与恢复是核心操作。本文使用 mongodump 和 mongorestore 工具&#xff0c;演示如何通过命令行导出和导入数据&#xff0c;解决副本集连接、路径指定等关键问题。 2. 数据导出&#xff08;mongodump&#xff09; 2.1 导出命…

京东 h5st 5.1 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 学习了2天某物&#xff0c;f…

CentOS 系统安装 docker 以及常用插件

博主用的的是WindTerm软件链接的服务器&#xff0c;因为好用 1.链接上服务器登入后&#xff0c;在/root/目录下 2.执行以下命令安装docker sudo yum install -y yum-utilssudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.reposudo…

不像人做的题————十四届蓝桥杯省赛真题解析(上)A,B,C,D题解析

题目A&#xff1a;日期统计 思路分析&#xff1a; 本题的题目比较繁琐&#xff0c;我们采用暴力加DFS剪枝的方式去做&#xff0c;我们在DFS中按照8位日期的每一个位的要求进行初步剪枝找出所有的八位子串&#xff0c;但是还是会存在19月的情况&#xff0c;为此还需要在CHECK函数…

【redis】set 类型:基本命令

文章目录 基本概念SADD 和 SMEMBERSSCARDSPOPSRANDMEMBERSMOVESREM集合间操作SINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令小结内部编码 基本概念 谈到一个属于&#xff0c;这个术语可能有多种含义&#xff0c;set 集合设置&#xff08;和 get 相对应&#xff09…

C 语言进【进阶篇】之动态内存管理:从底层机制到实战优化

目录 &#x1f680;前言&#x1f31f;动态内存分配的必要性&#x1f914;动态内存分配函数深度剖析&#x1f4af;malloc函数&#xff1a;内存申请的主力军&#x1f4af;free函数&#xff1a;释放内存的“清道夫”&#x1f4af;calloc函数&#xff1a;初始化内存的利器&#x1f…

2023华东师范大学计算机复试上机真题

2023华东师范大学计算机复试上机真题 2022华东师范大学计算机复试上机真题 2021华东师范大学计算机复试上机真题 2023华东师范大学计算机复试机试真题 2022华东师范大学计算机复试机试真题 2021华东师范大学计算机复试机试真题 在线评测&#xff1a;传送门&#xff1a;pgcode.…

Mac下安装Zed以及Zed对MCP(模型上下文协议)的支持

Zed是当前新流行的一种编辑器&#xff0c;支持MCP&#xff08;模型上下文协议&#xff09; Mac下安装Zed比较简单&#xff0c;直接有安装包&#xff0c;在这里&#xff1a; brew install --cask zedMac Monterey下是可以安装上的&#xff0c;亲测有效。 配置 使用CtrlShiftP…

Spring Boot 约定大于配置:实现自定义配置

文章目录 Spring Boot 约定大于配置&#xff1a;实现自定义配置引言1. Spring Boot 的约定大于配置2. 自定义配置的需求3. 实现自定义配置的步骤4. 示例&#xff1a;自定义 Spring MVC 配置4.1 创建自定义配置类4.2 创建自定义拦截器4.3 测试自定义配置 5. 其他自定义配置场景5…

交易系统优化方案

证券交易系统优化方案 一、选股策略体系 (一)择时策略矩阵 尾盘集中筛选法(14:30后)聚焦量价异动个股,捕捉次日溢价机会早盘转债套利法(9:25-10:00)通过可转债与正股联动性捕捉日内机会龙头战法(全时段)行业板块强度排序,锁定前三大市值龙头容量资金战法(中盘股适用…

在线Doc/Docx转换为PDF格式 超快速转换的一款办公软件 文档快速转换 在线转换免费转换办公软件

小白工具https://www.xiaobaitool.net/files/word-pdf/提供了一项非常实用的在线服务——将Doc或Docx格式的文档快速转换为PDF格式。这项服务不仅操作简单&#xff0c;而且转换效率高&#xff0c;非常适合需要频繁处理文档转换的用户。 服务特点&#xff1a; 批量转换&#x…

java学习总结(四)MyBatis多表

一、多表结构 学生表、班级表、课程表、班级课程表 二、一对一 一个学生只属于一个班级。 查询&#xff1a;id name age gender banjiName SELECT s.id,s.name,s.age,s.gender,b.id AS banjiId,b.name AS banjiName FROM student AS s INNER JOIN banji AS b ON s.banji_id…

大语言模型学习及复习笔记(1)语言模型的发展历程

1.大模型进入人们视野 ChatGPT 于2022年11月底上线 模型名称 发布时间 核心突破 GPT-3 2020年6月 首款千亿参数模型&#xff0c;少样本学习 GPT-3.5-Turbo 2022年11月 对话能力优化&#xff0c;用户级应用落地 GPT-4 2023年3月 多模态、强逻辑推理 GPT-4o / GPT-4…

【NLP】 3. Distributional Similarity in NLP(分布式相似性)

Distributional Similarity in NLP&#xff08;分布式相似性&#xff09; 分布式相似性&#xff08;Distributional Similarity&#xff09; 是自然语言处理&#xff08;NLP&#xff09;中的核心概念&#xff0c;基于“相似的单词出现在相似的上下文中”这一假设。它用于衡量单…

【C#学习】协程等待

来源GPT&#xff0c;仅记录学习 yield return WaitForEndOfFrame() 适用于 渲染结束后再执行代码&#xff0c;但 WebGL 可能不适合这个操作&#xff0c;会拖慢帧率。(渲染得太慢&#xff09; yield return null; 让代码在下一帧的 Update() 里继续运行&#xff0c;更加流畅。 …

【项目】负载均衡式在线OJ

负载均衡式在线OJ 目录 负载均衡式在线OJ 1.项目介绍&#xff1a; 2.comm 2.1 log.hpp 日志等级 开放式日志 时间戳工具 2.2 util.hpp TimeUtil类 PathUtil类 FileUtil类 StringUtil类 3.Compile_server 3.1compile_run.hpp RemoveTempFile CodeToDesc Start 3.…