默认入口
ts
import { /* ... */ } from '@tripo3d/utils';默认入口聚合了浏览器侧的通用工具:设备检测、Promise 工具、跳转/下载、文件名/MIME、文件读取、localStorage 包装。
设备检测
isMobileDevice
| 函数 | 签名 | 说明 |
|---|---|---|
isMobileDevice | (ua: string | null) => boolean | 识别 UA 是否为移动端浏览器(android / webos / iphone / ipod / blackberry / iemobile / opera mini) |
ts
import { isMobileDevice } from '@tripo3d/utils';
if (isMobileDevice(navigator.userAgent)) {
// 走移动端路径
}为什么要传参
显式传入 UA 而不是内部读 navigator,便于 SSR 场景下从请求 header 注入。空值返回 false,不会抛错。
Promise 工具
sleep
| 函数 | 签名 | 说明 |
|---|---|---|
sleep | (ms: number) => Promise<void> | 延迟 N 毫秒解决 Promise,常用于节流、动画衔接 |
ts
import { sleep } from '@tripo3d/utils';
await sleep(300);
console.log('300ms 后执行');pf(promise factory)
外部解构 resolve / reject 的 Promise 工厂——适合把"等用户操作完成"封成 Promise(如等待弹窗确认、等待 OAuth 回调)。
| 函数 | 签名 | 说明 |
|---|---|---|
pf<T, U = any> | () => { promise: Promise<T>, resolve: (v) => void, reject: (e) => void } | 返回 promise 与外部可调用的 resolve/reject |
ts
import { pf } from '@tripo3d/utils';
function waitForLogin() {
const { promise, resolve } = pf<string>();
// 在某个事件回调里调 resolve('token')
document.addEventListener('login-done', e => resolve(e.detail), { once: true });
return promise;
}
const token = await waitForLogin();跳转 / 下载
jump 和 download 都是基于动态 <a> 元素 + .click() 实现,无需手动管理 DOM。
| 函数 | 签名 | 说明 |
|---|---|---|
jump | (url: string, blank = true) => void | 导航到 URL,默认在新标签页打开。blank=false 替换当前页 |
download | (url: string, name?: string) => void | 触发浏览器下载。name 设置文件名(需同源或服务端配置 Content-Disposition) |
ts
import { download, jump } from '@tripo3d/utils';
jump('https://tripo3d.ai'); // 新标签页打开
jump('/dashboard', false); // 当前页跳转
download('https://example.com/file.zip'); // 下载,文件名由响应头决定
download('https://example.com/file.zip', 'my.zip'); // 下载并重命名(需同源)跨源下载文件名
浏览器只在同源或服务端 Content-Disposition 配合时才会接受 download 属性的文件名。跨源 CDN 上的文件,用户最终拿到的可能是原始文件名。
文件名 / MIME
getSuffix
| 函数 | 签名 | 说明 |
|---|---|---|
getSuffix | (file: File | string) => string | undefined | 提取文件扩展名(小写)。传 File 对象时,扩展名缺失会回退到 MIME 后段 |
ts
import { getSuffix } from '@tripo3d/utils';
getSuffix('https://cdn.example.com/x/a.PNG'); // 'png'
getSuffix(new File([], 'photo.JPEG')); // 'jpeg'
getSuffix(new File([], 'no-extension', { type: 'image/webp' })); // 'webp'(回退到 MIME)readFileAsDataURL
| 函数 | 签名 | 说明 |
|---|---|---|
readFileAsDataURL | (file: File) => Promise<string> | FileReader 包装,把 File 读成 base64 data URL。失败时 reject |
ts
import { readFileAsDataURL } from '@tripo3d/utils';
const dataUrl = await readFileAsDataURL(file); // 'data:image/png;base64,...'
img.src = dataUrl;localStorage 包装
带 JSON 序列化的 localStorage。仅在浏览器环境可用,SSR 时直接调用会抛 localStorage is not defined。
| 函数 | 签名 | 说明 |
|---|---|---|
getStorage<T> | (key: string) => T | null | JSON.parse 失败或 key 不存在返回 null。不会抛错 |
setStorage | (key: string, value: unknown) => void | JSON.stringify 后写入。值过大会触发 QuotaExceededError(未捕获) |
removeStorage | (key: string) => void | 删除 key |
ts
import { getStorage, removeStorage, setStorage } from '@tripo3d/utils';
interface UserPref {
theme: 'light' | 'dark';
lang: string;
}
setStorage('user-pref', { theme: 'dark', lang: 'zh-CN' });
const pref = getStorage<UserPref>('user-pref');
if (pref) console.log(pref.theme);
removeStorage('user-pref');下一步
- Date — dayjs 包装与时区
- Resource — AWS S3 上传
- Playground — 工具函数交互测试 + Tripo 图标集浏览