注意的点
- 取景框要设置css
pointer-events: none;,否则鼠标移动到取景框上时,会触发鼠标移动事件,导致位置抽搐。 - 图片幽灵缝隙问题,可以考虑
display: flex;或者其他的解决办法。 - 使用
transform代替top、left,避免回流,优化性能。 - 预览图的定位问题。
- 考虑取景框边框对放大预览图片的影响。
直接贴代码:
1 | <template> |
pointer-events: none;,否则鼠标移动到取景框上时,会触发鼠标移动事件,导致位置抽搐。display: flex;或者其他的解决办法。transform代替top、left,避免回流,优化性能。直接贴代码:
1 | <template> |
封装一个异步操作方法,确保传入的函数不会阻塞后续代码执行。
1 | composer require react/event-loop react/promise |
1 |
|
1 |
|
不要使用同步阻塞代码:
sleep()、file_get_contents() 等同步阻塞操作推荐异步操作方式:
1 | // 正确:使用 ReactPHP 的异步 HTTP 客户端 |
CPU 密集型任务:
Q: 为什么我的异步操作仍然阻塞?
A: 检查回调函数中是否包含同步阻塞代码,如 sleep()、file_get_contents() 等
Q: 如何处理 CPU 密集型任务?
A: 使用多进程方案,ReactPHP 不适合处理 CPU 密集型任务
1 |
|
这个封装提供了简单易用的异步操作方式,适用于大多数 ReactPHP 异步编程场景。
映射类型允许我们基于现有类型的属性,创建一个新类型,通常用于批量修改属性。
核心语法:
1 | type MappedType<T> = { |
Readonly<T>将所有属性设为只读:
1 | interface User { |
形象记忆:就像给所有门加上”禁止进入”的锁(readonly)
Partial<T>将所有属性变为可选:
1 | type PartialUser = Partial<User>; |
形象记忆:就像把所有必填字段变成”选填”(?)
Required<T>将所有属性变为必填(与 Partial 相反)
1 | type RequiredUser = Required<PartialUser>; |
Record<K, T>创建一个对象类型,其键为 K,值为 T
1 | type UserRoles = Record<string, "admin" | "user" | "guest">; |
形象记忆:就像创建一个”键值对”的表格
Pick<T, K>从 T 中选取指定的属性 K
1 | type UserName = Pick<User, "name">; |
形象记忆:就像从菜单中”点菜”(只选需要的)
Omit<T, K>从 T 中排除指定的属性 K
1 | type UserWithoutAge = Omit<User, "age">; |
形象记忆:就像从套餐中”删除”不想要的项
1 | type AddPrefix<T, Prefix extends string> = { |
形象记忆:就像给所有文件名加前缀
1 | type MakeNullable<T> = { |
形象记忆:就像给所有必填字段加上”可为空”的选项
1 | T extends U ? X : Y |
如果类型 T 可以赋值给 U,则结果为 X,否则为 Y
1 | type IsString<T> = T extends string ? true : false; |
形象记忆:就像做选择题(是/否)
1 | type ElementType<T> = T extends (infer U)[] ? U : never; |
形象记忆:就像从容器中”提取”内容
1 | type ResponseType<T> = T extends { error: any } |
形象记忆:就像交通信号灯(不同条件走不同分支)
当 T 是联合类型时,条件类型会自动分发:
1 | type ToArray<T> = T extends any ? T[] : never; |
形象记忆:就像批量处理邮件(每个收件人收到单独的邮件)
1 | type DeepReadonly<T> = { |
形象记忆:就像俄罗斯套娃,一层层深入
| 概念 | 记忆技巧 |
|---|---|
Readonly<T> |
给所有属性加”禁止修改”标签 |
Partial<T> |
把所有必填变成”选填” |
Pick<T,K> |
从菜单中”点菜” |
Omit<T,K> |
从套餐中”删除”不想要的 |
AddPrefix<T,P> |
给文件名加前缀 |
MakeNullable<T> |
给必填字段加”可为空”选项 |
IsString<T> |
做选择题(是/否) |
ElementType<T> |
从容器中”提取”内容 |
| 分布式条件类型 | 批量处理邮件(每个收件人单独处理) |
| 条件类型递归 | 俄罗斯套娃,一层层深入 |
在使用 Pinia 进行状态管理时,常规方法难以直接持久化存储包含函数的对象。因为 JSON.stringify()在序列化对象时会忽略函数。本文将介绍一种自定义的解决方案,实现包含函数对象的持久化。
确保项目中已经安装了 Pinia。如果没有安装,可以通过 npm 进行安装:
1 | npm install pinia |
实现自定义的持久化逻辑,通过将函数序列化为字符串存储,在恢复时再转换回函数。
1 | import { defineStore } from "pinia"; |
在 Vue 3 组件中使用上述定义的 Pinia 存储。
1 | <template> |
new Function()存在安全风险,如果存储的函数字符串来自不可信源,可能会执行恶意代码。通过上述方法,我们能够在 Pinia 中实现包含函数对象的持久化存储,解决常规持久化方案无法处理函数的问题。
在 Git 里,贮藏(stash)能够把你工作目录里未提交的修改保存起来,让你可以在之后恢复这些修改。
在建立贮藏之前,你可以使用以下命令查看当前工作目录的状态:
1 | git status |
该命令会显示哪些文件被修改、添加或者删除。
若你要把所有未提交的修改(包括已暂存和未暂存的)保存到一个贮藏中,可以使用下面的命令:
1 | git stash save "可选的贮藏描述信息" |
例如:
1 | git stash save "临时保存未完成的功能修改" |
如果你仅想贮藏已暂存的文件,可使用:
1 | git stash push -p |
然后按提示选择要贮藏的修改。
创建贮藏之后,你可以使用以下命令查看贮藏列表:
1 | git stash list |
输出结果可能如下:
1 | stash@{0}: On master: 临时保存未完成的功能修改 |
若你想恢复最近一次的贮藏,可以使用:
1 | git stash apply |
要是你想恢复特定的贮藏,可指定贮藏的编号,例如恢复stash@{0}:
1 | git stash apply stash@{0} |
恢复贮藏后,该贮藏依旧存在于贮藏列表中。若你想在恢复贮藏的同时将其从贮藏列表里移除,可以使用pop命令:
1 | git stash pop |
如果你想删除某个贮藏,可以使用以下命令:
1 | git stash drop stash@{0} |
若要删除所有贮藏,可使用:
1 | git stash clear |