# @enonic/ui-utils 中文文档

规范地址：https://npmcn.com/package/%40enonic/ui-utils/

版本：0\.7\.0
npm 元数据更新时间：2026-11-04T12:20:40.570Z
中文译文更新时间：2026-11-14T04:50:02.190Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40enonic/ui-utils
原文对照：https://npmcn.com/package/%40enonic/ui-utils/?lang=original
项目主页：https://github.com/enonic/npm-enonic-ui-toolkit#readme
源码仓库：https://github.com/enonic/npm-enonic-ui-toolkit

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：203 kB，21 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.12\.0
- 运行依赖：1 个
- peer 依赖：neverthrow ^8\.2\.0
- 首次发布：2026-09-07T06:45:11.600Z
- 最新版本发布：2026-11-04T12:20:39.708Z
- 近 30 天下载量：2336（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 8 个）

## 中文简介

Enonic UIs 的无框架帮助器:请求传输、短语查询、主密钥、任务投票和管理员事件枢纽

## 安装

```sh
npm install @enonic/ui-utils
```

也可以使用：`pnpm add @enonic/ui-utils`、`yarn add @enonic/ui-utils`、`bun add @enonic/ui-utils`

## README

# @enonic/ ui- utils

没有视图层的一切都有用:请求传输,i18n核心,值为 XP 窗体与分析并格式化他们的助手编辑,主密钥,任务随它而来 结束,管理员事件枢纽的浏览器侧面,管理员应用程序共享的主题,以及 储存在烤面包堆后面.

**这里没有导入组件或框架, 也没有读取它没有创建的文字 .** 这是包的全部价值——它可以从商店、工人、测试或代码中找到 完全没有DOM,一个函数的结果只取决于它的论据. 词来自 消费者,从自己的服务器上取来,然后传入。 例外情况是: 从性质上看环境:主题读取其存储和操作系统偏好 `window` 这个 被递出,该页面默认; `documentVisibility` 读取 `document` 已移交; `parseRelativeTime` 读取时钟,除非它被交出 `now`,以及 `dateFromTime` 答复时间 今天; 管理员事件中心从它得到的url导入它的客户端 .

```sh
pnpm add @enonic/ui-utils              # the errors, the i18n core and the values, no peers
pnpm add @enonic/ui-utils neverthrow   # plus the transport, from '@enonic/ui-utils/request'
```

中心客户端也是自己的入口, `@enonic/ui-utils/admin-events`,没有对等点:是它 这里的代码从运行时间 URL 中加载一个模块——客户端 XP 服务于中枢的 api. 也一样 xP菜单, `@enonic/ui-utils/admin-menu`: 这里写给 `document.head`时 它把装填器 XP 作为 `menu-loader` 扩展 `com.enonic.xp.app.main`也一样 任务投票, `@enonic/ui-utils/task`,出于运输的原因:它用它的 `ResultAsync`。 。 。 .

根条目解决了包外的任何问题. 运输是自己的入口, `@enonic/ui-utils/request`代码 `neverthrow`: 每一份请求均以 联合国 `ResultAsync`,因此运输的消费者安装并共享该类的一册. `neverthrow` 因此,这是一个可选的同行.

## 这是什么

| 导出 | 它会做什么 |
| --- | --- |
| `AppError` | 每次失败的基础 一揽子报告 - `name` 确是一种文辞, `cause` 骑着本地人 `Error` 选项 |
| `RequestError` | 错误状态的响应 : `status`,和身体的,这是 `message` 当身体是JSON 并且有一个, 否则状态文本 |
| `RequestAbortedError` | 请求通过 `signal` |
| `requestJson<T>(url, options?)` \* 联合国 | 获取 JSON 天体为 `ResultAsync<T, AppError>`· ; `options` 携带 `method`一个JSON序列化的 `body`, (中文(简体) ), `headers` 财务报告和审定财务报表 `signal` |
| `requestOptionalJson<T>(url, options?)` \* 联合国 | 同样,有204个或空的或 `null` 机构决心 `undefined` |
| `localize(phrases, key, ...values)` | 后面的短语 `key` 与 `{0}`\- 按位置填入的样式占位符;缺少的密钥是 `#key#` |
| `Translate` | 什么是应用程序手 `@enonic/ui`是因为 `I18nProvider`: 密钥和软件包的英文, 应用程序的文本或英文的出处 |
| `passthrough` | 页:1 `Translate` 无翻译的应用程序 |
| `fromPhrases(read)` | (单位:千美元) `Translate` 超过一个短语的地图,在呼叫时读取 |
| `fromLookup(has, get)` | (单位:千美元) `Translate` 一个有/得到对,作为一个 `Messages`\- 风格源报价 |
| `bindPhrases(translate, fragment)` | 输入 `t` 一个碎片,一个商店 或任何其它东西,一个出处 |
| `mergePhrases(fragments)` | 从包件的碎片中取出一个目录, 密钥作为类型保存; 密钥声明两次抛出 |
| `comparePhrases(catalog, bundle)` | 目录键为捆绑所缺,占位符设置不同的人 |
| `LocalDate`, (中文(简体) ), `LocalTime`, (中文(简体) ), `LocalDateTime` | XP的无区日期,时间和日期: `fromString` 财务报告和审定财务报表 `fromDate` 内, `toString` 财务报告和审定财务报表 `toDate` 出来, `equals` 按数值 |
| `DateTime` | XP的瞬间, `2015-04-17T06:00:30.250Z`;其域为世界协调时 |
| `GeoPoint`, (中文(简体) ), `Reference`, (中文(简体) ), `BinaryReference`, (中文(简体) ), `Link` | 属性持有的其他值,每个字符串和 `equals` |
| `parseTime`, (中文(简体) ), `parseDateTime` | `06:00[:30[.250]]`,以及 `2015-04-17` 加入这个组织.. `undefined` 其他的,包括一个转会日 |
| `formatDate`, (中文(简体) ), `formatTime` | 相同的字符串从一个 `Date` 或从小时、分和秒起 |
| `pad`, (中文(简体) ), `dateFromTime` | 在他们的后面,有许多小助手 |
| `parseRelativeTime(expression, now?)` | 页:1 `Date` 表格的默认名称 : `now`, (中文(简体) ), `+1d`, (中文(简体) ), `-2h +30m`· ; `isRelativeTime` 表示字符串是否为 |
| `userKey`, (中文(简体) ), `groupKey`, (中文(简体) ), `roleKey` | (单位:千美元) `PrincipalKey` 从其所属地区 |
| `isPrincipalKey(value)`, (中文(简体) ), `parsePrincipalKey(value)` | 字符串是按键还是按键 |
| `principalType`, (中文(简体) ), `principalId`, (中文(简体) ), `idProviderOf` | 键的部件返回; 角色没有 id 提供者 |
| `toPrincipal(record)` | (单位:千美元) `PrincipalRecord` 作为 `Principal` 它的钥匙说, `type` 填入——一次,答复为: `requestJson<PrincipalRecord[]>(url).map((rs) => rs.map(toPrincipal))` |
| `isUserRecord`, (中文(简体) ), `isGroupRecord`, (中文(简体) ), `isRoleRecord` | 仅需要钥匙和名称的记录 |
| `principalPath(key)` | 在用户应用程序显示的情况下: `/roles/<id>`, (中文(简体) ), `/<idProvider>/users/<id>` |
| `isSystemPrincipal(key)` | `su`, (中文(简体) ), `anonymous`,则 `system.` 作用和项目作用 |
| `SUPER_USER_KEY`, (中文(简体) ), `ANONYMOUS_USER_KEY`, (中文(简体) ), `*_ROLE`, (中文(简体) ), `SYSTEM_ID_PROVIDER` | xP 定义: `role:system.admin`, (中文(简体) ), `role:system.everyone`, (中文(简体) ), `role:cms.admin` 和其余部分 |
| `pollTask(tasksUrl, taskId, options?)` § 翻译: | `<tasksUrl>/<taskId>` 读取每个 `intervalMs` 直至 `FINISHED`页:1 `TaskInfo`,或 `FAILED`错误; `onProgress`, (中文(简体) ), `signal` 财务报告和审定财务报表 `readResult` |
| `taskProgressPercent(task)` § 翻译: | `current` 联 合 国 `total` 百分比,0,而总数不详 |
| `TaskFailedError` § 翻译: | 任务结束于 `FAILED`数字 : `message` 这是它所报道的, `task` 其最后信息 |
| `createAdminEvents(hubUrl)` 页:1 | 中心位于 `hubUrl`数字 : `connect()` 装入客户端一次; `subscribeTopic`, (中文(简体) ), `subscribeConnection`, (中文(简体) ), `subscribeSessionEnd` 直到未订阅 |
| `createTopicReaction(options)` 页:1 | 一个话题的信息解析并收集到一个批次中, 丢弃时 `visible` 与一个 `refresh` 启示,和 `refresh` 损失赔偿额 |
| `documentVisibility()` 页:1 | 页面 `visibilityState` 作为 `Readable<boolean>` 反应需要,对于一个应用程序,没有主机手 |
| `loadAdminMenu(loaderUrl)` ‡ | 页面上的 XP 菜单装入器, 自动挂起, 及其 api —— `mount(options)` 回复 `<xp-menu>` 东道主,以及 `unmount()` |
| `mountAdminMenu(loaderUrl, options?)` ‡ | 在无页地上加载器,然后加载一个; `autoOpen` 财务报告和审定财务报表 `hideButtonWhenOpen` ——菜单遵循存储主题本身 |
| `readTheme()`, (中文(简体) ), `writeTheme(theme)` | 用户选择的主题, `system` 没有存储; 写入存储并告诉页面 |
| `subscribeTheme(listener)` | 所选主题更改——在本页上,在另一个标签中,删除——直到未订阅 |
| `readResolvedTheme()`, (中文(简体) ), `subscribeResolvedTheme(listener)` | 要画的主题, `system` 由 OS 解答,以及用户切换或 OS 的更改 |
| `THEME_STORAGE_KEY`, (中文(简体) ), `THEME_CHANGE_EVENT` | 页:1 `localStorage` 条目和窗口事件 |
| `createNotifications()` | 一个烤面包堆的商店: `notify(tone, message, options?)` 答覆说, `dismiss`, (中文(简体) ), `dismissOwned`, (中文(简体) ), `clear`, (中文(简体) ), `pause`, (中文(简体) ), `resume`,以及 `notifications`,则 `Readable` 屏幕上的内容 |
| `NotificationOptions`, (中文(简体) ), `NotificationData` | 有多么敬酒 东道主的合约 `autoHide` 财务报告和审定财务报表 `lifetimeMs`附加时 `actions`, (中文(简体) ), `owner` 财务报告和审定财务报表 `onClose` - 还有堆上的一个条目 |
| `admit`, (中文(简体) ), `remove`, (中文(简体) ), `findDuplicate`, (中文(简体) ), `lifetimeFor`, (中文(简体) ), `isUrgent` | 保险单的纯品 `VISIBLE_LIMIT`, (中文(简体) ), `SHORT_LIFETIME_MS`, (中文(简体) ), `LONG_LIFETIME_MS` 财务报告和审定财务报表 `MAX_LIFETIME_MS`对于一个自己作曲的东道主来说 |
| \* 来自 `@enonic/ui-utils/request`从 `@enonic/ui-utils/admin-events`从 `@enonic/ui-utils/admin-menu`§ 从 `@enonic/ui-utils/task`。 。 。 . |  |

## 主题

XP的管理员应用程序——设置,内容工作室,菜单——分别发布并共享 一个主题: `enonic:theme` 输入 `localStorage`, (中文(简体) ), `light`, (中文(简体) ), `dark` 或者说 `system`这些 函数是合同,因此没有应用程序用手说明.

-   **入为实相.** 一个事件只是一个提示 再次读它: 一个听众听到的是什么 什麽 `readTheme` 答案,缺少或无效的条目是 `system`。 。 。 .
-   **每页都听到开关.** `storage` 只在其他标签上放火,所以 `writeTheme` (单位:千美元) 发送 `THEME_CHANGE_EVENT` 在窗口上,每一个捆绑在页面上听.
-   **听者闻有变化.** 永远不要在订阅上, 也不要为留下答案的写作 曾经; 每一个 `subscribe*` 返回其未订阅者,由调用者决定其监听时间.
-   **被屏蔽的存储读取为 `system`写着警告.**

内容工作室预绘脚本读取 `enonic:theme` 在任何捆绑的负载之前 此包外的密钥副本 .

## 通知

`createNotifications()` 是后面的商店吗 `Host.notify`,在应用程序本身的祝酒词后面: 什麽 `NotificationList` 从 `@enonic/ui-kit` 使。 。 。 这是一个工厂,不是一个实例: 应用程序创建一个,从自己的模块导出,并把它交给列表和每个 `Host` 它为山造了一座山——一个敬酒会通过 `host.notify` 土地在 东道主的堆栈,从来没有在第二。 它的政策是:

-   **一个像它一样,没有显示两次.** 同样的语气,信息 和主人是已经的祝酒词, 他们的解职又回来了;其寿命没有重新开始,重复者自己的选择——即: `onClose` 其中——被放弃,因为它从未显示。 两个老板也这么说 各各守其道.
-   **屏幕上三个,其余排队** 赞颂真主,超绝万物 终身,而不是复活时.
-   **警告或出错会持续30秒,其余5秒**,除非 `lifetimeMs` 说 否则或 `autoHide` 关闭; 一生过去什么 `setTimeout` 等会, `MAX_LIFETIME_MS`,为 被关在那里. `pause` 财务报告和审定财务报表 `resume` 保持和继续剩下的——名单要求他们徘徊 和焦点.
-   **`owner` 这是什么 `dismissOwned` 拿下来** 当吊销; `onClose` 名为一次 当祝酒散去的时候,无论用什么方法,和抛出的一种,都是报应的,不费任何代价.

```ts
export const notifications = createNotifications();

const dismiss = notifications.notify('success', 'Saved');
notifications.notify('info', 'Moved to /site/news', {
  actions: [{ label: '/site/news', onClick: () => select('/site/news') }],
});
notifications.notify('error', 'Live updates unavailable', { autoHide: false, owner: 'app:users' });
notifications.dismissOwned('app:users');
```

部分 [Enonic UI 工具包](https://github.com/enonic/npm-enonic-ui-toolkit)。 。 。 .

## 常见问题

### @enonic/ui-utils 是什么？

Enonic UIs 的无框架帮助器:请求传输、短语查询、主密钥、任务投票和管理员事件枢纽

### 如何安装 @enonic/ui-utils？

在项目目录运行 npm install @enonic/ui-utils，或使用 pnpm add / yarn add / bun add。

### @enonic/ui-utils 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @enonic/ui-utils 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @enonic/ui-utils 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.12\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @enonic/ui-utils 可以商用吗？

@enonic/ui-utils 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @enonic/ui-utils 的下载量有多少？

根据 npm 官方下载统计，@enonic/ui-utils 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,336 次，日均约 78 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @enonic/ui-utils 还在维护吗？

最新版本 0\.7\.0 发布于 2026/11/04（9 天前）；至今共发布 8 个版本，其中过去 12 个月发布了 8 个；首次发布于 2026/09/07。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

