环境检测与辅助
@jiess/utils/helper 模块提供三大类辅助功能:环境检测、响应式与网络工具、动态函数构造。
typescript
// 环境检测
import { getBrowserInfo, getOSInfo, getDeviceType, initSystemInfo } from '@jiess/utils/helper'
// 响应式与网络工具
import { shallowCopy, isReactive, getQuery, throwErr } from '@jiess/utils/helper'
// 动态函数(⚠️ 有安全风险,见下方说明)
import { customFuction, customAsyncFuction } from '@jiess/utils/helper'一、环境检测(environment.ts)
环境检测函数均接收 userAgent: string 参数,通常在浏览器端从 navigator.userAgent 获取,在服务端可从请求头获取。
getBrowserInfo(userAgent)
解析浏览器信息,返回完整的浏览器环境信息对象。
typescript
getBrowserInfo(navigator.userAgent)
// { appName, appVersion, platform, product, vendor, userAgent }
// 返回当前浏览器环境的完整信息,而非简化的 { browser, version }getOSInfo(userAgent)
检测操作系统类型。
typescript
getOSInfo(navigator.userAgent)
// 'Windows' | 'MacOS' | 'iOS' | 'Android' | 'Linux' | 'UNIX' | 'Unknown OS'
// 平台适配
const os = getOSInfo(navigator.userAgent)
if (os === 'iOS' || os === 'Android') {
applyMobileKeyboardFix()
}getDeviceInfo(userAgent)
返回具体设备名称(比 getDeviceType 更精细)。
typescript
getDeviceInfo(navigator.userAgent)
// 'iPhone' | 'iPad' | 'Android Device' | 'Windows Phone' | 'BlackBerry' | 'Mobile' | 'Tablet' | 'Desktop'getDeviceType(userAgent)
返回设备大类,支持检测小程序环境。
typescript
getDeviceType(navigator.userAgent)
// 'Desktop' | 'Mobile' | 'Tablet' | 'Applet'
// 按设备资源分配
switch (getDeviceType(navigator.userAgent)) {
case 'Mobile': reduceAnimation(); break
case 'Tablet': loadMdAssets(); break
case 'Applet': initMiniApp(); break
default: loadFullAssets()
}initSystemInfo(platform, space)
整合设备、OS、平台、环境、工作空间信息为统一标识字符串。
typescript
initSystemInfo('web', 'production')
// "Desktop ;Windows ;web ;development ;production"注意:
- 环境标识(第四段)始终硬编码为
'development',不反映实际运行环境。- 依赖
navigator.userAgent,仅能在浏览器环境中使用。
二、响应式与网络工具(jiess.ts)
isReactive(o) / isRef(v) / hasProxy(v)
判断对象是否为 Jiess 响应式代理。
typescript
import { isReactive, isRef, hasProxy } from '@jiess/utils/helper'
isReactive({ $jiess: true }) // true
isReactive({ a: 1 }) // false
// 在响应式渲染前判断类型
function renderValue(v: any) {
if (isReactive(v)) return renderProxy(v)
return v
}initValue(v)
提取响应式代理的原始值,非代理对象原样返回。
typescript
import { initValue } from '@jiess/utils/helper'
initValue({ $proxy: { value: 'hello' } }) // 'hello'
initValue({ a: 1 }) // { a: 1 }shallowCopy(data, isError?)
浅拷贝对象或数组。isError=true 时,非对象/数组抛出异常。
typescript
import { shallowCopy } from '@jiess/utils/helper'
const arr = [1, 2, { a: 3 }]
const copy = shallowCopy(arr)
copy[2] !== arr[2] // true(第三层是引用共享,浅拷贝特性)throwErr(type, msg)
抛出带类型标记的 Error,返回类型为 never。
typescript
import { throwErr } from '@jiess/utils/helper'
function validate(input: unknown) {
if (!input) throwErr('ValidationError', '输入不能为空')
}
try { validate(null) }
catch (e: any) {
e.message // "ValidationError Error:输入不能为空"
}getQuery()
解析当前页面 URL 的 query 参数。非浏览器环境返回 undefined。
⚠️ 同名参数只保留最后一个值。
typescript
import { getQuery } from '@jiess/utils/helper'
// URL: https://example.com?lang=zh&page=2
const query = getQuery()
// { lang: 'zh', page: '2' }
const lang = query?.lang || 'en'getHostname(url) / isIPv4(host)
网络地址处理工具。
typescript
import { getHostname, isIPv4 } from '@jiess/utils/helper'
getHostname('https://www.example.com/path') // 'www.example.com'
getHostname('http://localhost:3000') // 'localhost'
isIPv4('192.168.1.1') // true
isIPv4('256.0.0.1') // false
isIPv4('example.com') // falsegetWorkSpace(getSpace?) / getWorkInfo(platform, errFunc?)
获取工作空间标识与完整工作信息。
typescript
import { getWorkSpace, getWorkInfo } from '@jiess/utils/helper'
// 从 URL 的 $space 参数获取,若无 $space 则调用 getSpace 回调
// ⚠️ 不传 getSpace 且无 $space 参数时将抛出异常
const space = getWorkSpace() // 可能抛出 '未指定工作空间标识'
const space = getWorkSpace((params) => params.env || 'production') // 安全写法
// 异步获取完整工作信息,依赖 localStorage 和 navigator
const info = await getWorkInfo('web')
// "Desktop ;Windows ;web ;development ;production"
getWorkSpace在localStorage不可用(Node.js)时返回undefined。
三、动态函数构造(⚠️ 高风险)
customFuction(...arrs) / customAsyncFuction(...arrs)
从字符串动态创建可执行函数。底层分别使用 new Function() 和 AsyncFunction。
⚠️ 安全警告:本质是动态
eval,传入的代码字符串若来自用户输入或不可信来源,可能被注入恶意代码。调用方必须在传入前做白名单/沙箱校验。
| 参数 | 说明 |
|---|---|
...arrs | 最后一项为代码字符串,前面的项为参数名列表 |
typescript
import { customFuction, customAsyncFuction } from '@jiess/utils/helper'
// 同步:参数 "a,b" → 代码 "return a + b"
const add = customFuction('a', 'b', 'return a + b')
add(1, 2) // 3
// 异步
const fetch = customAsyncFuction('url', `
const res = await globalThis.fetch(url)
return res.json()
`)
fetch('/api/data').then(console.log)
// 错误处理(代码内抛出会通过 initError 捕获并上报)
const bad = customFuction('return notDefined')
bad() // 不抛异常,通过 initError 处理此功能主要用于 Jiess 脚本调试和动态规则引擎等受控场景。常规业务开发中不推荐使用。
类型导出
@jiess/utils/midder 同时导出以下 TypeScript 类型,用于类型注解:
| 类型 | 说明 |
|---|---|
ListenerConfig | 监听器配置 { listener: Function, tag?: string } |
DriverConfig | 触发器配置 { defaultValue: unknown, tag?: string } |
WatchEffectParam | watchEffect 参数 { flush?, onTrack?, onTrigger? } |
默认导出
@jiess/utils 也支持全量默认导入(不推荐,会失去 Tree-shaking):
typescript
import utils from '@jiess/utils'
utils.$clone({ a: 1 })边界情况
| 函数 | 边界行为 |
|---|---|
getDeviceType | 微信/支付宝/QQ/百度/字节小程序 UA 均识别为 'Applet' |
getOSInfo | 无法识别时返回 'Unknown OS' |
shallowCopy | isError=true 时字符串等非容器类型抛出异常 |
throwErr | 返回类型 never,TypeScript 能正确推断后续代码不可达 |
getQuery | 非浏览器环境返回 undefined;同名 key 只保留最后值 |
isIPv4 | 256.0.0.1 等非法范围返回 false |
customFuction | 代码字符串为空的函数直接返回 undefined |