UNPKG

@mt-kit/utils

Version:
2,427 lines (1,796 loc) 57.7 kB
# @mt-kit/utils ## 下载 ```bash npm i @mt-kit/utils ``` ## 使用 [See](https://github.com/Not-have/micro-tools/tree/main/packages-utils/stories) ## API ### animationFrameThrottle - 使用 `requestAnimationFrame` 创建函数节流版本,限制函数在特定时间内的调用次数 - 适用于高频事件如滚动、窗口大小改变等场景 | 参数名 | 说明 | 是否必传 | 类型 | |--------|------|----------|------| | fn | 需要节流的回调函数 | 是 | `Function` | **返回值:** `Function` - 节流后的函数 **使用场景:** - 滚动事件处理 - 窗口大小改变监听 - 动画更新函数 - 鼠标移动事件 ```ts import { animationFrameThrottle } from "@mt-kit/utils"; // 滚动事件处理 const handleScroll = () => { console.log('页面滚动中...'); }; window.addEventListener('scroll', animationFrameThrottle(handleScroll)); // 窗口大小改变 const handleResize = () => { console.log('窗口大小改变'); }; window.addEventListener('resize', animationFrameThrottle(handleResize)); // 动画效果 const updateAnimation = () => { // 更新动画逻辑 }; const throttledAnimation = animationFrameThrottle(updateAnimation); ``` ### imageBase64ToBlob - 将 Base64 格式的图片转换为 Blob 对象 - 支持各种图片格式(PNG、JPEG、GIF、WebP 等) | 参数名 | 说明 | 是否必传 | 类型 | |--------|------|----------|------| | base64 | Base64 格式的图片数据 | 是 | `string` | **返回值:** `Blob` - 转换后的 Blob 对象 **使用场景:** - 图片上传前的格式转换 - Canvas 导出图片 - 图片压缩处理 - 文件下载 ```ts import { imageBase64ToBlob } from "@mt-kit/utils"; // 转换 Base64 图片为 Blob const base64Data = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'; const blob = imageBase64ToBlob(base64Data); // 上传图片 const formData = new FormData(); formData.append('image', blob, 'image.png'); // 创建下载链接 const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'image.png'; a.click(); ``` ### imageUrlToBase64 - 将图片 URL 转换为 Base64 格式 - 支持跨域图片(需要服务器支持 CORS) | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | url | 图片的 URL 地址 | 是 | `string` | - | | mimeType | 生成的 Base64 字符串的 MIME 类型 | 否 | `string` | `"image/png"` | **返回值:** `Promise<string>` - Base64 格式的图片数据 **使用场景:** - 图片缓存处理 - 离线图片存储 - 图片压缩上传 - 图片预览功能 ```ts import { imageUrlToBase64 } from "@mt-kit/utils"; // 转换图片 URL 为 Base64 imageUrlToBase64('https://example.com/image.png') .then(base64 => { console.log(base64); // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA... // 在页面中显示 const img = document.createElement('img'); img.src = base64; document.body.appendChild(img); }) .catch(error => { console.error('图片转换失败:', error); }); // 指定 MIME 类型 imageUrlToBase64('https://example.com/image.jpg', 'image/jpeg') .then(base64 => { console.log(base64); // data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ... }); ``` ### downloadByUrl - 根据文件地址进行下载 - 支持各种文件格式(PDF、图片、文档等) | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | url | 文件的 URL 地址 | 是 | `string` | - | | target | 链接的打开方式 | 否 | `string` | `"_blank"` | | fileName | 下载的文件名 | 否 | `string` | 自动从 URL 提取 | **返回值:** `void` **使用场景:** - 文件下载功能 - 文档导出 - 图片保存 - 资源下载 ```ts import { downloadByUrl } from "@mt-kit/utils"; // 下载 PDF 文档 downloadByUrl({ url: 'https://example.com/document.pdf', target: '_blank', fileName: 'my-document.pdf' }); // 下载图片 downloadByUrl({ url: 'https://example.com/image.jpg', fileName: 'beautiful-image.jpg' }); // 下载 Excel 文件 downloadByUrl({ url: 'https://example.com/data.xlsx', fileName: 'report-2024.xlsx' }); ``` ### downloadDataFile - 根据文件数据进行下载 - 支持各种数据类型(文本、二进制、ArrayBuffer 等) | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | data | 文件数据(BlobPart 类型) | 是 | `BlobPart` | - | | filename | 保存的文件名 | 是 | `string` | - | | mime | 文件的 MIME 类型 | 否 | `string` | 自动检测 | **返回值:** `void` **使用场景:** - 动态生成文件下载 - 文本文件导出 - 二进制数据处理 - 数据备份功能 ```ts import { downloadDataFile } from "@mt-kit/utils"; // 下载文本文件 const textData = "Hello, World!"; downloadDataFile(textData, 'hello.txt', 'text/plain'); // 下载 JSON 数据 const jsonData = JSON.stringify({ name: 'John', age: 30 }, null, 2); downloadDataFile(jsonData, 'data.json', 'application/json'); // 下载二进制数据 const binaryData = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" downloadDataFile(binaryData, 'hello.bin', 'application/octet-stream'); // 下载 CSV 数据 const csvData = "Name,Age,City\nJohn,30,New York\nJane,25,London"; downloadDataFile(csvData, 'users.csv', 'text/csv'); ``` ### downloadBase64File - 根据 Base64 数据下载文件 - 支持各种文件格式的 Base64 数据 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | base64 | Base64 格式的文件数据 | 是 | `string` | - | | filename | 保存的文件名 | 是 | `string` | - | | mime | 文件的 MIME 类型 | 否 | `string` | 自动检测 | **返回值:** `void` **使用场景:** - Base64 图片下载 - 编码文件导出 - 数据恢复功能 - 文件格式转换 ```ts import { downloadBase64File } from "@mt-kit/utils"; // 下载 Base64 文本文件 const base64Text = 'data:text/plain;base64,SGVsbG8gV29ybGQh'; // "Hello World!" downloadBase64File(base64Text, 'hello.txt'); // 下载 Base64 图片 const base64Image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'; downloadBase64File(base64Image, 'image.png', 'image/png'); // 下载 Base64 PDF const base64Pdf = 'data:application/pdf;base64,JVBERi0xLjQKJcfsj6IK...'; downloadBase64File(base64Pdf, 'document.pdf', 'application/pdf'); ``` ### downloadUrlFile - 根据在线文件的 URL 进行下载 - 支持各种文件格式(图片、文档、视频等) | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | url | 文件的 URL 地址 | 是 | `string` | - | | filename | 保存的文件名 | 是 | `string` | - | | mime | 文件的 MIME 类型 | 否 | `string` | 自动检测 | **返回值:** `Promise<void>` **使用场景:** - 在线图片保存 - 文档下载 - 媒体文件下载 - 资源备份 ```ts import { downloadUrlFile } from "@mt-kit/utils"; // 下载图片 downloadUrlFile( 'https://example.com/image.png', 'my-image.png', 'image/png' ); // 下载 PDF 文档 downloadUrlFile( 'https://example.com/document.pdf', 'report.pdf', 'application/pdf' ); // 下载视频文件 downloadUrlFile( 'https://example.com/video.mp4', 'tutorial.mp4', 'video/mp4' ); ``` ### copyText - 复制文本到剪贴板 - 支持现代浏览器的 Clipboard API | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | text | 要复制的文本内容 | 是 | `string` | - | | fn | 复制成功的回调函数 | 否 | `Function` | - | **返回值:** `Promise<void>` **使用场景:** - 一键复制功能 - 分享链接复制 - 代码片段复制 - 用户反馈功能 ```ts import { copyText } from "@mt-kit/utils"; // 基本使用 copyText('Hello World!').then(() => { console.log('文本已复制到剪贴板'); }); // 带回调函数 copyText('https://example.com', () => { alert('链接已复制!'); }); // 错误处理 copyText('Some text') .then(() => { console.log('复制成功'); }) .catch(error => { console.error('复制失败:', error); }); ``` ### queryStringToObject - 将查询字符串转换为对象 - 支持 URL 参数解析和对象化处理 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | queryString | 查询字符串(包含 ? 或不包含都可以) | 是 | `string` | - | **返回值:** `Record<string, string>` - 解析后的参数对象 **使用场景:** - URL 参数解析 - 表单数据处理 - 路由参数提取 - API 参数构建 ```ts import { queryStringToObject } from "@mt-kit/utils"; // 基本使用 const query = queryStringToObject('?name=John&age=30'); console.log(query); // { name: 'John', age: '30' } // 不包含 ? 的字符串 const query2 = queryStringToObject('name=John&age=30'); console.log(query2); // { name: 'John', age: '30' } // 空查询字符串 const query3 = queryStringToObject(''); console.log(query3); // {} // 复杂参数 const query4 = queryStringToObject('?search=hello%20world&page=1&sort=desc'); console.log(query4); // { search: 'hello world', page: '1', sort: 'desc' } ``` ### openWindow - 打开新窗口 - 支持自定义窗口属性和打开方式 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | url | 要打开的链接地址 | 是 | `string` | - | | options | 窗口打开选项 | 否 | `object` | `{ target: '_blank' }` | **返回值:** `Window | null` - 新打开的窗口对象 **Options 配置项:** - `target`: 窗口打开方式(`_blank`, `_self`, `_parent`, `_top`) - `features`: 窗口特性(宽度、高度、位置等) **使用场景:** - 外部链接打开 - 弹窗功能 - 新页面跳转 - 第三方集成 ```ts import { openWindow } from "@mt-kit/utils"; // 基本使用 openWindow('https://example.com'); // 自定义窗口属性 openWindow('https://example.com', { target: '_blank', features: 'width=800,height=600,scrollbars=yes,resizable=yes' }); // 居中打开窗口 const windowFeatures = 'width=600,height=400,left=' + (screen.width / 2 - 300) + ',top=' + (screen.height / 2 - 200); openWindow('https://example.com', { target: '_blank', features: windowFeatures }); ``` ### cookieHelper - Cookie 操作助手 - 提供完整的 Cookie 增删改查功能 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | name | Cookie 名称 | 是 | `string` | - | | value | Cookie 值 | 是 | `string` | - | | options | Cookie 配置选项 | 否 | `object` | `{}` | **方法列表:** - `get(name)`: 获取指定名称的 Cookie - `set(name, value, options)`: 设置 Cookie - `remove(name)`: 删除指定名称的 Cookie **Options 配置项:** - `expires`: 过期时间(天数) - `path`: Cookie 路径 - `domain`: Cookie 域名 - `secure`: 是否只在 HTTPS 下传输 - `sameSite`: SameSite 属性 **使用场景:** - 用户登录状态 - 用户偏好设置 - 购物车数据 - 主题配置 ```ts import { cookieHelper } from "@mt-kit/utils"; // 设置 Cookie cookieHelper.set('username', 'John', { expires: 7 }); // 7天过期 cookieHelper.set('theme', 'dark', { path: '/', secure: true }); // 获取 Cookie const username = cookieHelper.get('username'); const theme = cookieHelper.get('theme'); // 删除 Cookie cookieHelper.remove('username'); // 设置带路径的 Cookie cookieHelper.set('session', 'abc123', { expires: 1, path: '/admin', secure: true, sameSite: 'strict' }); ``` ### localStorageHelper - localStorage 操作助手 - 提供本地存储的增删改查功能,支持 JSON 序列化 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | name | 本地存储的键名 | 是 | `string` | - | | value | 本地存储的值 | 是 | `any` | - | **方法列表:** - `get(name)`: 获取指定名称的本地存储 - `set(name, value)`: 设置本地存储 - `remove(name)`: 删除指定名称的本地存储 - `clear()`: 清空所有数据 **使用场景:** - 用户数据持久化 - 应用配置存储 - 缓存数据管理 - 离线数据存储 ```ts import { localStorageHelper } from "@mt-kit/utils"; // 设置数据 localStorageHelper.set('user', { name: 'John', age: 30 }); localStorageHelper.set('theme', 'dark'); localStorageHelper.set('settings', { language: 'zh-CN', currency: 'CNY' }); // 获取数据 const user = localStorageHelper.get('user'); const theme = localStorageHelper.get('theme'); const settings = localStorageHelper.get('settings'); // 删除数据 localStorageHelper.remove('user'); // 清空所有数据 localStorageHelper.clear(); // 处理不存在的键 const nonExistent = localStorageHelper.get('nonExistent'); console.log(nonExistent); // null ``` ### isElement - 判断是否为 DOM 元素 - 支持各种 DOM 元素类型检测 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | element | 要检测的元素 | 是 | `any` | - | **返回值:** `boolean` - 是否为 DOM 元素 **使用场景:** - DOM 操作前的类型检查 - 事件处理中的元素验证 - 组件库开发 - 工具函数开发 ```ts import { isElement } from "@mt-kit/utils"; // 检测 DOM 元素 const div = document.createElement('div'); console.log(isElement(div)); // true const span = document.createElement('span'); console.log(isElement(span)); // true // 检测非 DOM 元素 console.log(isElement({})); // false console.log(isElement('string')); // false console.log(isElement(123)); // false console.log(isElement(null)); // false console.log(isElement(undefined)); // false // 在事件处理中使用 document.addEventListener('click', (event) => { if (isElement(event.target)) { console.log('点击了 DOM 元素:', event.target); } }); ``` ### isFunction - 判断是否为函数 - 支持各种函数类型检测(普通函数、箭头函数、构造函数等) | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | fn | 要检测的值 | 是 | `any` | - | **返回值:** `boolean` - 是否为函数 **使用场景:** - 回调函数验证 - 高阶函数开发 - 事件处理器检查 - 工具函数开发 ```ts import { isFunction } from "@mt-kit/utils"; // 检测各种函数类型 console.log(isFunction(() => {})); // true - 箭头函数 console.log(isFunction(function() {})); // true - 普通函数 console.log(isFunction(async () => {})); // true - 异步函数 console.log(isFunction(function*() {})); // true - 生成器函数 console.log(isFunction(Array)); // true - 构造函数 console.log(isFunction(Math.max)); // true - 内置函数 // 检测非函数 console.log(isFunction({})); // false console.log(isFunction('string')); // false console.log(isFunction(123)); // false console.log(isFunction(null)); // false console.log(isFunction(undefined)); // false // 在回调中使用 function processCallback(callback) { if (isFunction(callback)) { callback('处理完成'); } else { console.error('回调必须是一个函数'); } } ``` ### isEqual - 深度比较两个值是否相等 - 支持对象、数组、基本类型的深度比较 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | a | 要比较的第一个值 | 是 | `any` | - | | b | 要比较的第二个值 | 是 | `any` | - | **返回值:** `boolean` - 两个值是否相等 **使用场景:** - 对象状态比较 - 表单数据验证 - 缓存数据检查 - 组件更新判断 ```ts import { isEqual } from "@mt-kit/utils"; // 基本类型比较 console.log(isEqual(1, 1)); // true console.log(isEqual('hello', 'hello')); // true console.log(isEqual(true, true)); // true console.log(isEqual(null, null)); // true console.log(isEqual(undefined, undefined)); // true // 对象深度比较 const objA = { a: 1, b: { c: 2 } }; const objB = { a: 1, b: { c: 2 } }; const objC = { a: 1, b: { c: 3 } }; console.log(isEqual(objA, objB)); // true console.log(isEqual(objA, objC)); // false // 数组比较 const arr1 = [1, 2, { a: 3 }]; const arr2 = [1, 2, { a: 3 }]; const arr3 = [1, 2, { a: 4 }]; console.log(isEqual(arr1, arr2)); // true console.log(isEqual(arr1, arr3)); // false // 复杂嵌套比较 const complex1 = { users: [ { id: 1, name: 'John', settings: { theme: 'dark' } } ], config: { api: 'https://api.example.com' } }; const complex2 = { users: [ { id: 1, name: 'John', settings: { theme: 'dark' } } ], config: { api: 'https://api.example.com' } }; console.log(isEqual(complex1, complex2)); // true ``` ### isNull - 判断是否为 null - 严格检查 null 值,不包括 undefined | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | value | 要检测的值 | 是 | `any` | - | **返回值:** `boolean` - 是否为 null **使用场景:** - 数据验证 - 空值检查 - 条件判断 - 类型守卫 ```ts import { isNull } from "@mt-kit/utils"; // 检测 null console.log(isNull(null)); // true // 检测非 null 值 console.log(isNull(undefined)); // false console.log(isNull(0)); // false console.log(isNull('')); // false console.log(isNull(false)); // false console.log(isNull({})); // false console.log(isNull([])); // false // 在条件判断中使用 function processValue(value) { if (isNull(value)) { console.log('值为 null'); } else { console.log('值不为 null:', value); } } processValue(null); // 值为 null processValue('hello'); // 值不为 null: hello ``` ### isObject - 判断是否为对象类型 - 包括普通对象、数组、函数等,但不包括 null | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | value | 要检测的值 | 是 | `any` | - | **返回值:** `boolean` - 是否为对象类型 **使用场景:** - 类型检查 - 对象操作前的验证 - 数据结构判断 - 工具函数开发 ```ts import { isObject } from "@mt-kit/utils"; // 检测对象类型 console.log(isObject({})); // true - 普通对象 console.log(isObject([])); // true - 数组 console.log(isObject(() => {})); // true - 函数 console.log(isObject(new Date())); // true - 日期对象 console.log(isObject(/regex/)); // true - 正则表达式 // 检测非对象类型 console.log(isObject(null)); // false console.log(isObject(undefined)); // false console.log(isObject('string')); // false console.log(isObject(123)); // false console.log(isObject(true)); // false // 在对象操作中使用 function processData(data) { if (isObject(data)) { console.log('处理对象数据:', data); // 安全地进行对象操作 Object.keys(data).forEach(key => { console.log(`${key}: ${data[key]}`); }); } else { console.log('数据不是对象类型'); } } ``` ### isUndefined - 判断是否为 undefined - 严格检查 undefined 值,不包括 null | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | value | 要检测的值 | 是 | `any` | - | **返回值:** `boolean` - 是否为 undefined **使用场景:** - 参数验证 - 可选属性检查 - 条件判断 - 类型守卫 ```ts import { isUndefined } from "@mt-kit/utils"; // 检测 undefined console.log(isUndefined(undefined)); // true // 检测非 undefined 值 console.log(isUndefined(null)); // false console.log(isUndefined(0)); // false console.log(isUndefined('')); // false console.log(isUndefined(false)); // false console.log(isUndefined({})); // false console.log(isUndefined([])); // false // 在函数参数中使用 function greet(name, greeting) { if (isUndefined(name)) { console.log('请提供姓名'); return; } const message = isUndefined(greeting) ? 'Hello' : greeting; console.log(`${message}, ${name}!`); } greet(); // 请提供姓名 greet('John'); // Hello, John! greet('John', 'Hi'); // Hi, John! // 在对象属性检查中使用 const user = { name: 'John' }; if (isUndefined(user.age)) { console.log('年龄未设置'); } ``` ### clone - 浅拷贝对象 - 只复制对象的第一层属性,嵌套对象保持引用 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | value | 要拷贝的值 | 是 | `any` | - | **返回值:** `any` - 拷贝后的对象 **使用场景:** - 对象状态备份 - 避免直接修改原对象 - 快速对象复制 - 性能要求较高的场景 ```ts import { clone } from "@mt-kit/utils"; // 基本对象拷贝 const obj = { a: 1, b: { c: 2 } }; const cloned = clone(obj); console.log(cloned); // { a: 1, b: { c: 2 } } console.log(cloned === obj); // false - 不是同一个对象 console.log(cloned.b === obj.b); // true - 嵌套对象引用相同 // 数组拷贝 const arr = [1, 2, { x: 3 }]; const clonedArr = clone(arr); console.log(clonedArr); // [1, 2, { x: 3 }] console.log(clonedArr === arr); // false console.log(clonedArr[2] === arr[2]); // true - 嵌套对象引用相同 // 修改拷贝后的对象 cloned.a = 10; console.log(obj.a); // 1 - 原对象不受影响 console.log(cloned.a); // 10 - 拷贝对象已修改 // 修改嵌套对象 cloned.b.c = 20; console.log(obj.b.c); // 20 - 原对象的嵌套对象也被修改 console.log(cloned.b.c); // 20 - 拷贝对象的嵌套对象也被修改 ``` ### cloneDeep - 深拷贝对象 - 递归复制所有嵌套对象,完全独立于原对象 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | value | 要拷贝的值 | 是 | `any` | - | **返回值:** `any` - 深拷贝后的对象 **使用场景:** - 完全独立的对象复制 - 状态管理 - 数据备份 - 避免引用污染 ```ts import { cloneDeep } from "@mt-kit/utils"; // 基本对象深拷贝 const obj = { a: 1, b: { c: 2 } }; const cloned = cloneDeep(obj); console.log(cloned); // { a: 1, b: { c: 2 } } console.log(cloned === obj); // false - 不是同一个对象 console.log(cloned.b === obj.b); // false - 嵌套对象也是独立的 // 复杂嵌套对象 const complex = { users: [ { id: 1, profile: { name: 'John', settings: { theme: 'dark' } } } ], config: { api: 'https://api.example.com' } }; const clonedComplex = cloneDeep(complex); console.log(clonedComplex.users[0] === complex.users[0]); // false console.log(clonedComplex.users[0].profile === complex.users[0].profile); // false // 修改深拷贝后的对象 cloned.b.c = 20; console.log(obj.b.c); // 2 - 原对象不受影响 console.log(cloned.b.c); // 20 - 拷贝对象已修改 // 数组深拷贝 const arr = [1, 2, { x: 3, y: { z: 4 } }]; const clonedArr = cloneDeep(arr); clonedArr[2].y.z = 40; console.log(arr[2].y.z); // 4 - 原数组不受影响 console.log(clonedArr[2].y.z); // 40 - 拷贝数组已修改 ``` ### debounce - 创建一个防抖函数,延迟调用函数直到上一次调用后的一段时间已经过去 - 适用于频繁触发的事件,如搜索输入、窗口调整等 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | fn | 要防抖的函数 | 是 | `Function` | - | | wait | 延迟时间(毫秒) | 是 | `number` | - | | options | 配置选项 | 否 | `object` | `{}` | **返回值:** `Function` - 防抖后的函数 **Options 配置项:** - `leading`: 是否在延迟开始前调用 - `trailing`: 是否在延迟结束后调用 - `maxWait`: 最大等待时间 **使用场景:** - 搜索输入防抖 - 窗口大小调整 - 按钮点击防抖 - API 请求优化 ```ts import { debounce } from "@mt-kit/utils"; // 搜索输入防抖 const debouncedSearch = debounce((query) => { console.log('搜索:', query); fetchSearchResults(query); }, 300); // 在输入框中使用 const input = document.getElementById('search'); input.addEventListener('input', (e) => { debouncedSearch(e.target.value); }); // 窗口大小调整防抖 const debouncedResize = debounce(() => { console.log('窗口大小已调整'); updateLayout(); }, 250); window.addEventListener('resize', debouncedResize); // 按钮点击防抖 const debouncedClick = debounce(() => { console.log('按钮被点击'); submitForm(); }, 1000); document.getElementById('submitBtn').addEventListener('click', debouncedClick); // 带配置选项的防抖 const debouncedWithOptions = debounce((data) => { console.log('处理数据:', data); }, 500, { leading: true, // 立即执行第一次 trailing: true, // 延迟结束后执行 maxWait: 2000 // 最大等待 2 秒 }); ``` ### throttle - 创建一个节流函数,限制函数在一段时间内只能调用一次 - 适用于需要定期执行但不想过于频繁的场景 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | fn | 要节流的函数 | 是 | `Function` | - | | wait | 节流时间(毫秒) | 是 | `number` | - | | options | 配置选项 | 否 | `object` | `{}` | **返回值:** `Function` - 节流后的函数 **Options 配置项:** - `leading`: 是否在节流开始前调用 - `trailing`: 是否在节流结束后调用 **使用场景:** - 滚动事件节流 - 鼠标移动事件 - 动画更新 - 性能优化 ```ts import { throttle } from "@mt-kit/utils"; // 滚动事件节流 const throttledScroll = throttle(() => { console.log('滚动位置更新'); updateScrollPosition(); }, 100); // 在滚动事件中使用 window.addEventListener('scroll', throttledScroll); // 鼠标移动节流 const throttledMouseMove = throttle((event) => { console.log('鼠标位置:', event.clientX, event.clientY); updateMousePosition(event); }, 16); // 约 60fps document.addEventListener('mousemove', throttledMouseMove); // 窗口大小调整节流 const throttledResize = throttle(() => { console.log('窗口大小调整'); updateLayout(); }, 200); window.addEventListener('resize', throttledResize); // 带配置选项的节流 const throttledWithOptions = throttle((data) => { console.log('处理数据:', data); }, 500, { leading: true, // 立即执行第一次 trailing: true // 节流结束后执行 }); // 动画更新节流 const throttledAnimation = throttle(() => { updateAnimationFrame(); }, 16); // 60fps function startAnimation() { const animate = () => { throttledAnimation(); requestAnimationFrame(animate); }; animate(); } ``` ### omitBy - 创建一个从对象中排除满足条件的属性的新对象 - 根据条件函数过滤对象属性 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | obj | 源对象 | 是 | `object` | - | | condition | 用于判断是否排除属性的条件函数 | 是 | `Function` | - | **返回值:** `object` - 过滤后的新对象 **使用场景:** - 对象属性过滤 - 数据清理 - 条件性属性排除 - 对象转换 ```ts import { omitBy } from "@mt-kit/utils"; // 基本使用 - 排除值大于 2 的属性 const sampleObject = { a: 1, b: 2, c: 3, d: 4, }; const result = omitBy(sampleObject, (value) => value > 2); console.log(result); // { a: 1, b: 2 } // 排除空值 const dataWithEmpty = { name: 'John', age: 30, email: '', phone: null, address: undefined }; const cleanedData = omitBy(dataWithEmpty, (value) => value === '' || value === null || value === undefined ); console.log(cleanedData); // { name: 'John', age: 30 } // 排除特定类型的属性 const mixedData = { id: 1, name: 'John', isActive: true, createdAt: new Date(), tags: ['admin', 'user'] }; const stringOnly = omitBy(mixedData, (value) => typeof value !== 'string'); console.log(stringOnly); // { name: 'John' } // 排除特定键名的属性 const userData = { id: 1, name: 'John', password: 'secret', email: 'john@example.com', token: 'abc123' }; const publicData = omitBy(userData, (value, key) => key === 'password' || key === 'token' ); console.log(publicData); // { id: 1, name: 'John', email: 'john@example.com' } ``` ### objectValueToString - 将对象的值转换为字符串 - 保持对象结构不变,只转换值类型 | 参数名 | 说明 | 是否必传 | 类型 | 默认值 | |--------|------|----------|------|--------| | obj | 源对象 | 是 | `object` | - | **返回值:** `object` - 值转换为字符串的新对象 **使用场景:** - 数据序列化准备 - 表单数据处理 - API 参数转换 - 数据格式统一 ```ts import { objectValueToString } from "@mt-kit/utils"; // 基本使用 const obj = { id: 123, active: true, score: 98.5 }; const stringified = objectValueToString(obj); console.log(stringified); // 输出: { id: '123', active: 'true', score: '98.5' } // 复杂对象 const complexObj = { user: { id: 1, name: 'John', age: 30, isActive: true }, settings: { theme: 'dark', notifications: false, language: 'zh-CN' }, scores: [85, 92, 78] }; const stringifiedComplex = objectValueToString(complexObj); console.log(stringifiedComplex); // 输出: { // user: { id: '1', name: 'John', age: '30', isActive: 'true' }, // settings: { theme: 'dark', notifications: 'false', language: 'zh-CN' }, // scores: ['85', '92', '78'] // } // 处理特殊值 const specialObj = { nullValue: null, undefinedValue: undefined, emptyString: '', zero: 0, falseValue: false }; const stringifiedSpecial = objectValueToString(specialObj); console.log(stringifiedSpecial); // 输出: { // nullValue: 'null', // undefinedValue: 'undefined', // emptyString: '', // zero: '0', // falseValue: 'false' // } ``` ### IframeMessage - 创建一个 iframe 通信工具,与内嵌的页面进行双向通讯 - 支持父子页面之间的消息传递和事件监听 **主要方法:** - `createIframe(url)`: 创建 iframe 元素 - `postMessage(message)`: 发送消息 - `onMessage(callback)`: 监听消息 - `removeMessageListener(callback)`: 移除消息监听 **使用场景:** - 跨域页面通信 - 微前端架构 - 嵌入式应用 - 父子页面数据同步 **调用界面(父页面):** ```tsx import { JSX, useCallback, useMemo } from "react"; import { IframeMessage } from "@mt-kit/utils"; export default function DemoIframeMessage(): JSX.Element { const url = "http://localhost:5173/"; const iframe = useMemo(() => { const communicator = new IframeMessage(); communicator.createIframe(url); return communicator; }, [url]); const handleClick = useCallback(() => { iframe.postMessage({ type: "message", data: { name: "hello", age: 18 } }); }, [iframe]); return ( <div> <p>iframe 通信</p> <button onClick={handleClick}>传值</button> </div> ); } ``` **接收通信(子页面):** ```vue <script setup lang="ts"> import { onMounted, onUnmounted } from "vue"; import { Message, IframeMessage } from "@mt-kit/utils"; const iframe = new IframeMessage(); const handleMessage = (e: Message): void => { console.log('收到消息:', e); // 处理不同类型的消息 switch (e.type) { case 'message': console.log('数据:', e.data); break; case 'command': console.log('命令:', e.data); break; } }; onMounted(() => { iframe.onMessage(handleMessage); }); onUnmounted(() => { iframe.removeMessageListener(handleMessage); }); </script> <template> <div> <h1>子页面</h1> <p>等待接收消息...</p> </div> </template> ``` **双向通信示例:** ```ts // 父页面 const iframe = new IframeMessage(); iframe.createIframe('http://localhost:5173/'); // 监听子页面消息 iframe.onMessage((message) => { console.log('父页面收到:', message); }); // 发送消息到子页面 iframe.postMessage({ type: 'userData', data: { userId: 123, name: 'John' } }); // 子页面 const iframe = new IframeMessage(); // 监听父页面消息 iframe.onMessage((message) => { console.log('子页面收到:', message); // 回复消息给父页面 iframe.postMessage({ type: 'response', data: { status: 'received' } }); }); ``` ### flattenAndSort 将对象扁平化为键值对并按键排序,确保输出结果的确定性。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `obj` | `Record<string, unknown>` | ✅ | - | 要扁平化的对象 | | `prefix` | `string` | ❌ | `""` | 键前缀,用于嵌套对象的键名 | **返回值:** | 类型 | 说明 | |------|------| | `Record<string, string>` | 扁平化的对象,所有值都转换为字符串 | **特性:** - **确定性输出**: 通过按键排序确保相同输入产生相同输出 - **递归处理**: 自动处理嵌套对象 - **类型安全**: 所有值统一转换为字符串 - **空值处理**: `undefined` 和 `null` 转换为空字符串 **使用示例:** ```typescript import { flattenAndSort } from '@mt-kit/utils'; // 基础用法 const obj = { name: 'John', age: 30, address: { city: 'New York', country: 'USA' } }; const result = flattenAndSort(obj); // 结果: { // "address.city": "New York", // "address.country": "USA", // "age": "30", // "name": "John" // } // 带前缀 const resultWithPrefix = flattenAndSort(obj, 'user'); // 结果: { // "user.address.city": "New York", // "user.address.country": "USA", // "user.age": "30", // "user.name": "John" // } ``` **应用场景:** - 对象序列化前的预处理 - 生成确定性哈希值 - 对象比较和去重 - 配置文件的扁平化处理 --- ### arrayBufferToBase64 将 ArrayBuffer 转换为 Base64 字符串,提供安全高效的转换。 **参数:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `buffer` | `ArrayBuffer` | ✅ | 要转换的 ArrayBuffer | **返回值:** | 类型 | 说明 | |------|------| | `string` | Base64 编码的字符串,失败时返回空字符串 | **特性:** - **容错处理**: 输入无效时返回空字符串,不抛出异常 - **高效转换**: 使用 `String.fromCharCode` 进行安全转换 - **类型验证**: 自动验证输入是否为有效的 ArrayBuffer - **错误日志**: 失败时输出警告信息便于调试 **使用示例:** ```typescript import { arrayBufferToBase64 } from '@mt-kit/utils'; // 基础用法 const buffer = new ArrayBuffer(8); const view = new Uint8Array(buffer); view[0] = 72; // 'H' view[1] = 101; // 'e' view[2] = 108; // 'l' view[3] = 108; // 'l' view[4] = 111; // 'o' const base64 = arrayBufferToBase64(buffer); console.log(base64); // "SGVsbG8=" // 错误处理 const invalid = arrayBufferToBase64(null as any); console.log(invalid); // "" // 从文件读取 const file = new File(['Hello'], 'test.txt'); const reader = new FileReader(); reader.onload = (e) => { const base64 = arrayBufferToBase64(e.target?.result as ArrayBuffer); console.log(base64); }; reader.readAsArrayBuffer(file); ``` **应用场景:** - 文件上传前的编码 - 图片数据处理 - 二进制数据传输 - 加密数据存储 --- ### sha256Base64 将字符串转换为 SHA-256 哈希的 Base64 编码,提供安全的哈希功能。 **参数:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `str` | `string` | ✅ | 要哈希的字符串 | **返回值:** | 类型 | 说明 | |------|------| | `Promise<string>` | Base64 编码的 SHA-256 哈希值 | **特性:** - **异步处理**: 使用 Web Crypto API 进行异步哈希计算 - **安全算法**: 使用 SHA-256 算法确保安全性 - **Base64 输出**: 直接输出 Base64 编码,便于存储和传输 - **错误处理**: 哈希失败时抛出错误,便于上层处理 **使用示例:** ```typescript import { sha256Base64 } from '@mt-kit/utils'; // 基础用法 const hash = await sha256Base64('Hello World'); console.log(hash); // "pZGm1Av0IEBKARCz7JZcLAuUx7QgTz+ekpJZeBc7uT0=" // 密码哈希 const password = 'myPassword123'; const passwordHash = await sha256Base64(password); console.log(passwordHash); // 文件内容哈希 const fileContent = 'file content here'; const fileHash = await sha256Base64(fileContent); console.log(fileHash); // 错误处理 try { const hash = await sha256Base64('test'); console.log(hash); } catch (error) { console.error('哈希生成失败:', error); } ``` **应用场景:** - 密码存储和验证 - 数据完整性校验 - 唯一标识符生成 - 缓存键生成 --- ### getAvailableFonts 检测系统中可用的字体列表,支持批量检测和容错处理。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `fontList` | `string[]` | ❌ | `COMMON_FONTS` | 要检测的字体列表 | **返回值:** | 类型 | 说明 | |------|------| | `string[]` | 可用的字体列表 | **特性:** - **Canvas 检测**: 使用 Canvas 2D 上下文进行字体检测 - **批量处理**: 支持同时检测多个字体 - **容错机制**: 单个字体检测失败不影响其他字体 - **精度控制**: 使用宽度差异阈值避免浮点数精度问题 - **详细日志**: 提供检测过程和结果的详细日志 **使用示例:** ```typescript import { getAvailableFonts } from '@mt-kit/utils'; // 检测常用字体 const availableFonts = getAvailableFonts(); console.log(availableFonts); // ['Arial', 'Helvetica', 'Times New Roman', ...] // 检测自定义字体列表 const customFonts = ['CustomFont', 'AnotherFont', 'Arial']; const available = getAvailableFonts(customFonts); console.log(available); // ['Arial'] (假设其他字体不可用) // 空列表处理 const empty = getAvailableFonts([]); console.log(empty); // [] ``` **检测原理:** 1. 使用回退字体测量基准宽度 2. 使用目标字体测量文本宽度 3. 比较宽度差异,超过阈值则认为字体可用 4. 阈值设置为 0.1px,避免浮点数精度问题 **应用场景:** - 字体回退策略 - 设备指纹生成 - 字体兼容性检测 - 动态字体加载 --- ### measureTextWidthDom 使用 DOM 元素测量文本宽度,提供精确的文本尺寸测量。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `text` | `string` | ✅ | - | 要测量的文本 | | `font` | `string` | ✅ | - | 字体样式 | | `size` | `string` | ❌ | `FONT_CONFIG.size` | 字体大小 | **返回值:** | 类型 | 说明 | |------|------| | `number` | 文本宽度(像素),测量失败返回 -1 | **特性:** - **DOM 测量**: 使用真实的 DOM 元素进行测量 - **样式隔离**: 创建隐藏元素避免影响页面布局 - **强制重排**: 确保样式生效后再测量 - **自动清理**: 测量完成后自动移除临时元素 - **错误处理**: 测量失败时返回 -1 **使用示例:** ```typescript import { measureTextWidthDom } from '@mt-kit/utils'; // 基础用法 const width = measureTextWidthDom('Hello World', 'Arial'); console.log(width); // 82.5 // 自定义字体大小 const width2 = measureTextWidthDom('Test', 'Times New Roman', '16px'); console.log(width2); // 24.8 // 错误处理 const invalid = measureTextWidthDom('', 'InvalidFont'); console.log(invalid); // -1 ``` **应用场景:** - 文本布局计算 - 字体检测 - 动态宽度调整 - 文本溢出处理 --- ### measureTextWidthCanvas 使用 Canvas 2D 上下文测量文本宽度,提供高性能的文本尺寸测量。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `text` | `string` | ✅ | - | 要测量的文本 | | `font` | `string` | ✅ | - | 字体样式 | | `size` | `string` | ❌ | `FONT_CONFIG.size` | 字体大小 | **返回值:** | 类型 | 说明 | |------|------| | `number` | 文本宽度(像素),测量失败返回 -1 | **特性:** - **Canvas 测量**: 使用 Canvas 2D 上下文进行测量 - **高性能**: 不操作 DOM,性能优于 DOM 方法 - **高精度**: 设置固定 Canvas 尺寸确保测量精度 - **错误处理**: 测量失败时返回 -1 - **类型安全**: 验证测量结果的数值有效性 **使用示例:** ```typescript import { measureTextWidthCanvas } from '@mt-kit/utils'; // 基础用法 const width = measureTextWidthCanvas('Hello World', 'Arial'); console.log(width); // 82.5 // 自定义字体大小 const width2 = measureTextWidthCanvas('Test', 'Times New Roman', '16px'); console.log(width2); // 24.8 // 批量测量 const texts = ['Short', 'Medium Length Text', 'Very Long Text Here']; const widths = texts.map(text => measureTextWidthCanvas(text, 'Arial')); console.log(widths); // [32.5, 95.2, 158.7] ``` **Canvas vs DOM 对比:** | 特性 | Canvas | DOM | |------|--------|-----| | 性能 | ✅ 高 | ❌ 低 | | 精度 | ✅ 高 | ✅ 高 | | 兼容性 | ✅ 好 | ✅ 好 | | 内存使用 | ✅ 低 | ❌ 高 | | 布局影响 | ✅ 无 | ❌ 有 | **应用场景:** - 字体检测(推荐) - 批量文本测量 - 性能敏感场景 - 字体指纹生成 ### createContainer - 创建容器 - 支持自定义元素插入到容器中 - 支持追加到容器中 - 支持追加到 body - 支持追加到指定元素 **参数:** | 参数 | 说明 | 是否必传 | 默认值 | |--------|------|----------|--------| | positionOptions | 位置选项 | 否 | 所有功能启用 | | append | 是否追加到容器中 | 否 | false | | customElement | 自定义元素 | 否 | 无 | **返回值:** | 类型 | 说明 | |--------|------| | `{ remove: () => void; element: HTMLDivElement; }` | 容器 | **positionOptions 参数:** | 参数 | 说明 | 是否必传 | 默认值 | |--------|------|----------|--------| | position | 位置 | 否 | 无 | **append 参数:** | 参数 | 说明 | 是否必传 | 默认值 | |--------|------|----------|--------| | append | 是否追加到容器中 | 否 | false | **customElement 参数:** | 参数 | 说明 | 是否必传 | 默认值 | |--------|------|----------|--------| | customElement | 自定义元素 | 否 | 无 | **使用示例:** ```ts import { createContainer } from "@mt-kit/utils"; const container = createContainer(); console.log(container); ``` ### uuid - 生成唯一的 ID - 使用 Date.now() 和 Math.random() 生成唯一的 ID - 使用 slice(2, 15) 生成唯一的 ID - 使用 _ 连接 - 使用 toString(36) 生成唯一的 ID ```ts import { uuid } from "@mt-kit/utils"; const id = uuid(); console.log(id); ``` ## 设备信息 ### deviceAll - 获取所有设备信息(包括同步和异步信息) | 参数名 | 说明 | 是否必传 | 默认值 | |--------|------|----------|--------| | options | 配置选项,可禁用某些功能 | 否 | 所有功能启用 | 返回类型:`Promise<IDeviceAll>` **Options 配置项:** - `operatingSystem`: 是否获取操作系统信息 - `browser`: 是否获取浏览器信息 - `language`: 是否获取语言信息 - `onLine`: 是否获取在线状态 - `screen`: 是否获取屏幕信息 - `cpuCores`: 是否获取CPU核心数 - `hardwareConcurrency`: 是否获取硬件并发数 - `memory`: 是否获取内存信息 - `features`: 是否获取设备特性 - `sensor`: 是否获取传感器信息 - `i18n`: 是否获取国际化信息 - `location`: 是否获取地理位置(异步) - `publicIp`: 是否获取公网IP(异步) ```ts import { deviceAll } from "@mt-kit/utils"; // 获取完整设备信息 const allDeviceInfo = await deviceAll(); console.log(allDeviceInfo); // 禁用某些功能 const basicInfo = await deviceAll({ location: false, // 不获取地理位置 publicIp: false, // 不获取公网IP memory: false // 不获取内存信息 }); // 只获取基础信息 const minimalInfo = await deviceAll({ operatingSystem: true, browser: true, language: true, onLine: true, screen: false, cpuCores: false, hardwareConcurrency: false, memory: false, features: false, sensor: false, i18n: false, location: false, publicIp: false }); ``` ### deviceOperatingSystem - 获取操作系统信息 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | ```ts import { deviceOperatingSystem } from "@mt-kit/utils"; const os = deviceOperatingSystem(); console.log(os); // "Windows", "macOS", "Linux", "Android", "iOS", "unknown" ``` ### deviceBrowser - 获取浏览器信息 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`IBrowser` ```ts import { deviceBrowser } from "@mt-kit/utils"; const browser = deviceBrowser(); console.log(browser); // { name: "Chrome", version: "120.0.0.0" } ``` ### deviceLanguage - 获取浏览器语言 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | ```ts import { deviceLanguage } from "@mt-kit/utils"; const language = deviceLanguage(); console.log(language); // "zh-CN", "en-US", etc. ``` ### deviceOnLine - 获取在线状态 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | ```ts import { deviceOnLine } from "@mt-kit/utils"; const isOnline = deviceOnLine(); console.log(isOnline); // true or false ``` ### deviceScreen - 获取屏幕信息 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`IScreen` ```ts import { deviceScreen } from "@mt-kit/utils"; const screen = deviceScreen(); console.log(screen); // { // width: 1920, // height: 1080, // availWidth: 1920, // availHeight: 1040, // colorDepth: 24, // pixelDepth: 24, // devicePixelRatio: 1 // } ``` ### deviceLocation - 获取地理位置信息(需要用户授权) | 参数名 | 说明 | 是否必传 | 返回值 | |--------|------|----------|--------| | 无 | 无参数 | - | `{ latitude: number, longitude: number }` | 返回类型:`Promise<ILocation>` **返回值说明:** - `latitude`: 纬度,范围 -9090 - `longitude`: 经度,范围 -180180 **失败情况:** - **定位服务不可用**:返回 `{ latitude: 0, longitude: 0 }` - **用户拒绝授权**:返回 `{ latitude: -1, longitude: -1 }` - **超时**:返回 `{ latitude: -1, longitude: -1 }` - **其他错误**:返回 `{ latitude: -1, longitude: -1 }` ```ts import { deviceLocation } from "@mt-kit/utils"; deviceLocation().then(location => { if (location.latitude === -1 && location.longitude === -1) { console.log("定位失败或用户拒绝授权"); } else { console.log(`位置: ${location.latitude}, ${location.longitude}`); } }); ``` ### devicePublicIp **IP查询服务列表:** 1. `https://api.ipify.org?format=json` - 官方服务,稳定可靠 2. `https://ipapi.co/json/` - 官方 API,功能丰富 3. `https://ipinfo.io/json` - 官方服务,数据准确 4. `https://api.ip.sb/geoip` - 开源项目,稳定 5. `https://httpbin.org/ip` - 官方测试服务 **服务特点:** - 按顺序尝试,成功即停止 - 总超时时间:15秒 - 单个服务超时:5秒 - 全部失败时返回 `127.0.0.1` | 参数名 | 说明 | 是否必传 | 返回值 | |--------|------|----------|--------| | 无 | 无参数 | - | `string` | 返回类型:`Promise<string>` **返回值说明:** - 成功时:返回公网IP地址字符串,如 `"203.208.60.1"` - 失败时:返回本地IP地址 `"127.0.0.1"` 作为容错处理 - 可能包含位置信息:`"203.208.60.1 (北京市)"` ```ts import { devicePublicIp } from "@mt-kit/utils"; devicePublicIp().then(ip => { console.log(ip); // "127.0.0.1" (获取失败时返回本地IP) }); ``` ### deviceCpuCores - 获取CPU核心数 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | ```ts import { deviceCpuCores } from "@mt-kit/utils"; const cores = deviceCpuCores(); console.log(cores); // 8 ``` ### deviceMemory - 获取内存信息 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`IMemory` ```ts import { deviceMemory } from "@mt-kit/utils"; const memory = deviceMemory(); console.log(memory); // { // usedJSHeapSize: 43.18, // totalJSHeapSize: 46.07, // jsHeapSizeLimit: 4095.75, // deviceMemory: 8 // } ``` ### deviceHardwareConcurrency - 获取硬件并发数 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | ```ts import { deviceHardwareConcurrency } from "@mt-kit/utils"; const concurrency = deviceHardwareConcurrency(); console.log(concurrency); // 8 ``` ### deviceFeatures - 获取设备特性支持 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`IFeatures` ```ts import { deviceFeatures } from "@mt-kit/utils"; const features = deviceFeatures(); console.log(features); // { // touchSupport: true, // maxTouchPoints: 5, // vibrate: true, // webglSupport: true, // webrtcSupport: true // } ``` ### deviceSensor - 获取传感器支持 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`ISensor` ```ts import { deviceSensor } from "@mt-kit/utils"; const sensor = deviceSensor(); console.log(sensor); // { // accelerometer: true, // gyroscope: true, // magnetometer: false, // ambientLight: false, // barometer: false // } ``` ### deviceI18n - 获取国际化信息 | 参数名 | 说明 | 是否必传 | |--------|------|----------| | 无 | 无参数 | - | 返回类型:`II18n` ```ts import { deviceI18n } from "@mt-kit/utils"; const i18n = deviceI18n(); console.log(i18n); // { // timeZone: "Asia/Shanghai", // daylightSaving: false, // numberFormat: "1,234.56", // currencyFormat: "¥1,234.56", // dateFormat: "2024/1/1", // timeFormat: "14:30:00" // } ``` ## 获取设备指纹 ### fingerprint 生成综合设备指纹,整合多种指纹信息创建唯一标识符。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `strength` | `boolean` | ❌ | `true` | 是否生成强指纹(包含屏幕信息) | **返回值:** | 类型 | 说明 | |------|------| | `Promise<string>` | SHA-256 哈希的 Base64 编码指纹字符串 | **指纹组成:** - **设备信息**: 操作系统、浏览器、屏幕等基础信息 - **Canvas 指纹**: 基于 Canvas 渲染的像素数据 - **WebGL 指纹**: 显卡硬件信息 - **音频指纹**: 音频处理特征 - **字体指纹**: 可用字体列表 - **国际化信息**: 时区、语言、数字格式等 **特性:** - **综合指纹**: 整合多种指纹信息提高唯一性 - **确定性**: 相同环境产生相同指纹 - **容错处理**: 单个指纹失败不影响整体结果 - **强度控制**: 可选择是否包含屏幕信息 **使用示例:** ```typescript import { fingerprint } from '@mt-kit/utils'; // 生成强指纹(包含屏幕信息) const strongFingerprint = await fingerprint(true); console.log(strongFingerprint); // "a1b2c3d4e5f6..." // 生成弱指纹(不包含屏幕信息) const weakFingerprint = await fingerprint(false); console.log(weakFingerprint); // "x1y2z3a4b5c6..." // 默认强指纹 const defaultFingerprint = await fingerprint(); console.log(defaultFingerprint); // "m1n2o3p4q5r6..." ``` **指纹稳定性:** | 因素 | 影响程度 | 说明 | |------|----------|------| | 屏幕分辨率 | 🔴 高 | 改变分辨率会改变指纹 | | 浏览器版本 | 🟡 中 | 更新可能影响指纹 | | 操作系统 | 🔴 高 | 不同系统指纹不同 | | 硬件配置 | 🔴 高 | 显卡、音频设备影响指纹 | | 字体安装 | 🟡 中 | 字体变化影响指纹 | **应用场景:** - 用户身份识别 - 设备唯一标识 - 反爬虫检测 - 用户行为分析 - 安全验证 **注意事项:** - 指纹可能因环境变化而改变 - 建议结合其他身份验证方式 - 遵守隐私法规,明确告知用户 - 定期更新指纹算法以提高安全性 <details> <summary>生成指纹的原理 API 列表</summary> #### fingerprintFonts 生成字体指纹,通过检测可用字体列表创建设备指纹。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `fonts` | `string[]` | ❌ | `COMMON_FONTS` | 要检测的字体列表 | **返回值:** | 类型 | 说明 | |------|------| | `string` | 可用字体列表的逗号分隔字符串 | **特性:** - **字体检测**: 基于 Canvas 2D 上下文检测字体可用性 - **批量处理**: 支持检测多个字体 - **容错机制**: 单个字体检测失败不影响整体结果 - **确定性输出**: 相同字体列表产生相同结果 **使用示例:** ```typescript import { fingerprintFonts } from '@mt-kit/utils'; // 检测默认字体列表 const fontFingerprint = fingerprintFonts(); console.log(fontFingerprint); // "Arial,Helvetica,Times New Roman,Georgia" // 检测自定义字体列表 const customFonts = ['CustomFont', 'AnotherFont', 'Arial']; const customFingerprint = fingerprintFonts(customFonts); console.log(customFingerprint); // "Arial" (假设其他字体不可用) ``` **应用场景:** - 设备指纹生成 - 字体兼容性检测 - 浏览器环境识别 - 反爬虫检测 --- #### fingerprintCanvas 生成 Canvas 指纹,通过渲染特定内容获取设备特定的渲染特征。 **参数:** 无参数 **返回值:** | 类型 | 说明 | |------|------| | `string` | Canvas 渲染数据的像素值字符串,失败时返回空字符串 | **特性:** - **渲染指纹**: 基于 Canvas 2D 渲染结果生成指纹 - **固定内容**: 使用固定的文本和样式确保一致性 - **像素采样**: 提取特定位置的像素值作为指纹 - **容错处理**: 渲染失败时返回空字符串 **渲染内容:** - 文本: 使用固定字体渲染特定文本 - 图形: 绘制矩形和半透明文本 - 采样: 提取前 100 个像素的 RGB 值 **使用示例:** ```typescript import { fingerprintCanvas } from '@mt-kit/utils'; // 生成 Canvas 指纹 const canvasFingerprint = fingerprintCanvas(); console.log(canvasFingerprint); // "255,0,0,0,0,255,102,204,0,..." // 错误处理 if (!canvasFingerprint) { console.warn('Canvas 指纹生成失败'); } ``` **技术原理:** 1. 创建 200x50 像素的 Canvas 2. 设置固定的字体和样式 3. 渲染文本和图形内容 4. 提取图像数据的 RGB 像素值 5. 按固定间隔采样并拼接成字符串 **应用场景:** - 设备指纹生成 - 浏览器环境识别 - 反爬虫检测 - 用户行为分析 --- #### fingerprintWebgl 生成 WebGL 指纹,通过获取显卡信息创建硬件指纹。 **参数:** 无参数 **返回值:** | 类型 | 说明 | |------|------| | `string` | WebGL 厂商和渲染器信息,失败时返回空字符串 | **特性:** - **硬件指纹**: 基于显卡硬件信息生成指纹 - **调试扩展**: 使用 `WEBGL_debug_renderer_info` 扩展获取详细信息 - **厂商信息**: 包含显卡厂商和渲染器型号 - **容错处理**: 不支持时返回空字符串 **获取信息:** - **厂商**: 显卡厂商名称(如 NVIDIA、AMD、Intel) - **渲染器**: 显卡型号和驱动信息 **使用示例:** ```typescript import { fingerprintWebgl } from '@mt-kit/utils'; // 生成 WebGL 指纹 const webglFingerprint = fingerprintWebgl(); console.log(webglFingerprint); // "NVIDIA Corporation~NVIDIA GeForce RTX 3080/PCIe/SSE2" // 检查支持情况 if (!webglFingerprint) { console.warn('WebGL 调试扩展不支持'); } ``` **兼容性:** - **桌面浏览器**: Chrome、Firefox、Safari 支持较好 - **移动浏览器**: 支持有限,很多移动浏览器禁用此扩展 - **隐私模式**: 可能被禁用或返回受限信息 **应用场景:** - 设备指纹生成 - 硬件环境识别 - 反爬虫检测 - 用户设备分析 --- #### fingerprintAudio 生成音频指纹,通过音频处理获取设备特定的音频特征。 **参数:** 无参数 **返回值:** | 类型 | 说明 | |------|------| | `Promise<string>` | 音频处理数据的样本值字符串,失败时返回空字符串 | **特性:** - **音频处理**: 基于 Web Audio API 生成音频指纹 - **离线渲染**: 使用 OfflineAudioContext 避免播放音频 - **固定参数**: 使用固定的音频参数确保一致性 - **样本采样**: 提取特定位置的音频样本值 **音频配置:** - **采样率**: 44.1kHz - **声道数**: 单声道 - **振荡器**: 三角波,1000Hz - **压缩器**: 固定参数配置 **使用示例:** ```typescript import { fingerprintAudio } from '@mt-kit/utils'; // 生成音频指纹 const audioFingerprint = await fingerprintAudio(); console.log(audioFingerprint); // "0.1,0.2,0.3,0.4,0.5,..." // 错误处理 try { const fingerprint = await fingerprintAudio(); if (!fingerprint) { console.warn('音频指纹生成失败'); } } catch (error) { console.error('音频处理错误:', error); } ``` **技术原理:** 1. 创建 OfflineAudioContext 2. 生成三角波振荡器 3. 通过动态压缩器处理音频 4. 离线渲染音频数据 5. 提取特定间隔的样本值 **应用场景:** - 设备指纹生成 - 音频环境识别 - 反爬虫检测 - 用户设备分析 --- </details>