# @equinor/fusion-framework-plugin-context-navigation 中文文档

规范地址：https://npmcn.com/package/%40equinor/fusion-framework-plugin-context-navigation/

版本：1\.1\.1
npm 元数据更新时间：2026-11-12T09:57:49.618Z
中文译文更新时间：2026-11-13T20:34:56.856Z
软件包许可：未声明

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

原始 npm 页面：https://www.npmjs.com/package/%40equinor/fusion-framework-plugin-context-navigation
原文对照：https://npmcn.com/package/%40equinor/fusion-framework-plugin-context-navigation/?lang=original
源码仓库：https://github.com/equinor/fusion-framework

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

- 包体积（解压后）：814 kB，256 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：rxjs ^7\.8\.1，@equinor/fusion-framework-module ^6\.2\.0，@equinor/fusion-framework-module-app ^8\.3\.0，@equinor/fusion-framework-module-event ^6\.1\.4，@equinor/fusion-framework-module-context ^9\.1\.0，@equinor/fusion-framework-module-navigation ^8\.0\.0
- 首次发布：2026-08-06T08:57:15.061Z
- 最新版本发布：2026-11-12T09:57:49.359Z
- 近 30 天下载量：6725（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：17（近 12 个月 17 个）

## 中文简介

基于适应器的合并框架门户上下文与URL调和器

## 安装

```sh
npm install @equinor/fusion-framework-plugin-context-navigation
```

也可以使用：`pnpm add @equinor/fusion-framework-plugin-context-navigation`、`yarn add @equinor/fusion-framework-plugin-context-navigation`、`bun add @equinor/fusion-framework-plugin-context-navigation`

## README

# 上下文导航插件( E)`@equinor/fusion-framework-plugin-context-navigation`(中文(简体) )

Fusion Framework门户网站由事件驱动的上下文到URL调节器插件. 它通过对上下文变化和app开关的反应,将上下文编码入URL,以及可选地防范手动URL编辑来降低上下文来保持活性上下文与浏览器URL同步.

## 何时使用

当您的插件 **门户** 需要:

-   自动反映浏览器 URL 中的活性上下文( 项目、 设施等)
-   支持多个 URL 编码策略( 路径段、 查询参数, 或 app自定义自定义编码)
-   在整个应用程序开关和页面重载中保留上下文
-   通过手动编辑 URL 防止用户意外丢失上下文

> \[注\] 此插件用于 **门户主机**,而不是个人申请. 应用程序通过应用程序的显示表来声明其首选的路由策略 `build.options.contextRouting` 字段——门户的上下文导航插件 抓取该声明并自动应用正确的 URL 编码 .

## 对于应用程序开发者

您不需要安装或配置此插件 。 门户能处理. 你唯一的责任是 **声明上下文应如何出现在您的 URL**。 。 。 .

### 宣布路线战略

设定 `contextRouting` 在你的应用清单 `build.options`数字 :

```jsonc
// app.manifest.config.ts
export default defineAppManifest((env) => ({
  // ...
  build: {
    options: {
      contextRouting: 'query',  // or 'path', or omit for default path behavior
    },
  },
}));
```

| 数值 | URL 形状 | 何时使用 |
| --- | --- | --- |
| `'path'` (或省略) | `/apps/{appKey}/{contextId}/sub-route` | 默认——没有复杂路由的简单应用程序 |
| `'query'` | `/apps/{appKey}/route?$contextId={id}` | 与上下文段相冲突的基于路径的子路由应用程序 |

有自定义 URL 形状的应用程序应当省略 `contextRouting` 并登记自定义钩(见下文).

> \[注\] 何时 `contextRouting` 未设定( 或设定为 `null`),门户默认为 **路径适配器** 将上下文编码为应用程序键后的一个路径段. 如果应用程序注册自定义钩( I)`setContextPathExtractor` 编号 : `setContextPathGenerator`),自定义适配器优先于路径 路径/默认路由的适配器 。 明确 `contextRouting: 'query'` 选择 查询适配器,即使已注册自定义路径钩.

### 自定义URL形状

如果您的应用程序将上下文编码为非标准位置( 例如 ) . `/route-a/{contextId}` 改为 `/{contextId}/route-a`),在应用程序上下文中注册自定义钩 配置 :

```ts
// app config
builder.setContextPathExtractor((pathname) => {
  // Extract context id from your custom URL position
  const segments = pathname.split('/').filter(Boolean);
  return segments[1]; // e.g. /route-a/{contextId} → contextId
});

builder.setContextPathGenerator((context, pathname) => {
  // Generate a URL with context in your custom position
  const segments = pathname.split('/').filter(Boolean);
  const route = segments[0] ?? '';
  return `/${route}/${context.id}`;
});
```

当这些钩子注册后, 插件的自定义适配器会将其取出 自动——无显示 `contextRouting` 需要声明.

应用程序拥有其 URL 形状, 因此 URL 是 URL 守护的真实来源 :

-   提取器未返回上下文的路由( 例如列表页, 如 `/categories`)是一条路线 **无** 上下文。 URL 守护器没有设置 积极的背景 回到它.
-   提取器返回不活动上下文的路由(例如链接) 从列表页到 `/app/{key}`)在推动和 替换模式,并在无上下文活动时替换.
-   在无上下文的路由中清除上下文使用户保持在那里. 在有上下文导航到应用根的路径上清除上下文 .
-   在没有上下文的路由中选择上下文仍然导航到 路径从 `generatePathFromContext`。 。 。 .

提取值不一定是上下文 ID。 如果这是一把钥匙或一发子弹, uRL 守护器将 URL 视为同步 `generatePathFromContext` 写入 对当前环境的同样价值。 所以在同一个背景中航行 不会再解决了 返回路径不变的生成器不会 来证明什么,所以守护者从 URL 中解析值. 在不相干的路由片段中重复的密钥不会触发另一个查询.

当 URL 守护从 URL 中解析上下文时, 查找属于此 URL (中文(简体) ). 如果用户在搜索完成前在别处导航, 守卫 取消它:迟到的结果既不改变上下文,也不改变用户的方向. 应用软件解职、应用开关和模块装入也取消了等待检查, 甚至在下一个导航事件之前,或者当目的地没有上下文模块时.

## 用于门户开发者

本README的其余部分涵盖门户级设置和配置.

## 关键概念

| 概念 | 说明 |
| --- | --- |
| **适配器** | 自选URL编码器/解码器. 每个适配器宣布 `canHandle()` 提供 `encode()` 编号 : `decode()` 方法。 。 . |
| **调试器** | 监视上下文+应用程序变化并触发URL出同步后导航的被动循环. |
| **URL 守护** | 如果外部导航将上下文从 URL 掉出, 可选的二次订阅会重新应用上下文编码 . |
| **来源** | 驱动调和器的可观察工厂——决定是应用开关还是上下文变化优先. |

### 如何运作

1.  **观察** ——调节器通过可配置源厂来监视当前应用和当前上下文.
2.  **解析适配器** - 对于每个应用程序,第一个适配器 `canHandle()` 返回时 `true` 已选定.
3.  **编码** ——所选适配器将上下文编码为目标URL.
4.  **比较** ——如果目标URL与当前URL不同,则导航会继续.
5.  **调度** - 可取消的 `onContextNavigationNavigate` 事件火灾。 听者可以打电话 `preventDefault()` 以中止.
6.  **导航** ——框架导航模块实现URL更新.
7.  **确认** - 一个 `onContextNavigationNavigated` 导航完成后发生事件起火.

## 安装

```sh
pnpm add @equinor/fusion-framework-plugin-context-navigation
```

## 快速启动

### 端口(应用程序开关铅)

一个应用门户网站一次显示一个应用. 当用户切换应用时, 调节器 取出新应用程序的上下文并将其编码入URL. 这是默认行为.

```ts
import { enableContextNavigation } from '@equinor/fusion-framework-plugin-context-navigation';

export const configure = (configurator) => {
  enableContextNavigation(configurator, (builder) => {
    builder.setPortalName('app-portal');
    builder.setDebug(true);
  });
};
```

默认源厂( E)`createAppFirstSource`手表( 手表 ) `app.current$` 财务报告和审定财务报表 在向调和器发送前先解决应用程序的上下文模块。 当应用程序 切换发生,新应用程序的活性上下文驱动URL更新.

### 上下文门户( 文本更改铅)

环绕一个共同的环境(例如一个项目)组织一个上下文门户。 当 用户选择上下文,导航立即更新 URL ——无论 该应用程序已激活。 清除上下文可返回门户根 .

```ts
import { enableContextNavigation } from '@equinor/fusion-framework-plugin-context-navigation';
import { createContextFirstSource } from '@equinor/fusion-framework-plugin-context-navigation/sources';

export const configure = (configurator) => {
  enableContextNavigation(configurator, (builder) => {
    builder.setPortalName('context-portal');
    builder.setSourceFactory(createContextFirstSource());
    builder.setNullContextUrl('/');
    builder.setDebug(true);
  });
};
```

与app-portal的关键差异 :

-   **`createContextFirstSource()`** ——上下文变化为主触发;应用模块作为依赖解决.
-   **`setNullContextUrl('/')`** – 当上下文被清除后, 导航到出入口登陆页面, 而不是授权适配器 .

## 内建适应器

装有3个适配器的插件船按优先顺序评估:

| 适配器 | URL 形状 | 选中时 |
| --- | --- | --- |
| **自定义** | App 定义( 通过 `generatePathFromContext` 编号 : `extractContextIdFromPath` 钩子) | App 提供自定义钩子, 不声明 `contextRouting: 'query'` |
| **查询** | `/apps/{appKey}/route?$contextId={id}` | 应用显示声明 `build.options.contextRouting: 'query'` |
| **路径** | `/apps/{appKey}/{contextId}/sub-route` | 默认倒计时——匹配 `contextRouting` 实值 `'path'`, (中文(简体) ), `null`,或省略 |

当没有注册自定义适配器时,所有三个内置适配器都可以使用. 第一个 `canHandle()` 返回时 `true` 当前应用程序获胜.

### 注册自定义适配器

您可以为内置集未覆盖的 URL 形状注册自己的适配器 . 这个 `canHandle` 选择适配器时的上方控件——使用任何信号 备查 `AdapterResolutionContext` (app key, URL, 上下文提供者, 路由策略).

```ts
import type { ContextNavigationAdapter } from '@equinor/fusion-framework-plugin-context-navigation/adapters';

const hashAdapter: ContextNavigationAdapter = {
  id: 'hash',
  // Select this adapter for a specific app that uses hash-based context
  canHandle: ({ appKey }) => appKey === 'my-hash-app',
  encode: ({ context, currentURL }) => {
    const url = new URL(currentURL.href);
    url.hash = context ? `#ctx=${context.id}` : '';
    return url;
  },
  decode: (url) => {
    const match = url.hash.match(/^#ctx=(.+)$/);
    return match?.[1] ?? null;
  },
};

enableContextNavigation(configurator, (builder) => {
  builder.registerAdapter(hashAdapter);
  // NOTE: registering any adapter disables built-in defaults.
  // Register all adapters you need explicitly.
});
```

## 配置

| 构建方法 | 默认 | 说明 |
| --- | --- | --- |
| `registerAdapter(adapter)` | 内置套装 | 登记导航适配器(对象或工厂)。 第一场比赛获胜. |
| `setPortalName(name)` | `'Portal'` | 调试日志输出中使用的名称 . |
| `setOrigin(origin)` | `window.location.origin` | 构建绝对 URL 的出处 . |
| `setUrlGuard(enabled)` | `true` | 如果外部导航从 URL 中掉入, 则重新同步上下文 。 与 `replace: false`,后向导航从 URL 更新上下文,而不是覆盖上下文。 带有自定义路径钩子的 Apps 总是将 URL 视为真理的来源(参见 [自定义URL形状](https://npmcn.com/package/%40equinor/fusion-framework-plugin-context-navigation/#readme-custom-url-shapes)) (中文(简体) ). |
| `setDebug(enabled)` | `false` | 启用动词 `console.debug` 输出. |
| `setNullContextUrl(urlOrFn)` | —— 说 | 函数( 或静态字符串) , 将 URL 返回到上下文被清除时的导航 。 接收 `{ appKey, currentURL }`。 。 。 . |
| `setRequireValidContext(enabled)` | `false` | 对照 app 上下文模块验证上下文( )`validateContext`)通航前. 如果验证失败, 导航会被跳过 . |
| `setNavigationOptions(options)` | `{ replace: true }` | 转到 `navigation.navigate()` uRL更新期间。 设定 `{ replace: false }` 来将历史条目推出 —— 然后从 URL 同步上下文, 而不是重新输入活动上下文 . |
| `setOnTransition(fn)` | —— 说 | 副作用钩在每次成功导航后呼叫. |
| `setSourceFactory(factory)` | `createAppFirstSource()` | 驱动调和器的可观察源厂. |

## 活动

该插件通过Fusion框架事件系统发送事件. 通过 `framework.event.addEventListener()`。 。 。 .

| 活动 | 何时 | 可取消 |
| --- | --- | --- |
| `onContextNavigationNavigate` | 在导航——适配器解决之前,目标 URL 计算 | **对** |
| `onContextNavigationNavigated` | 导航完成后 | 没有 |
| `onContextNavigationAdapterResolved` | 当为应用程序选择适配器时 | 没有 |
| `onContextNavigationSkipped` | 当调节决定不导航时 | 没有 |

### 跳过原因

这个 `onContextNavigationSkipped` 事件包括a `reason` 字段 :

| 原因 | 含义 |
| --- | --- |
| `'url-matches'` | 目标 URL 已经匹配当前 URL |
| `'no-context'` | 上下文为 `undefined` (仍在初始化) |
| `'no-adapter'` | 没有适配器能处理当前应用程序 |
| `'invalid-app-context'` | `setRequireValidContext(true)` 设置, 且应用程序上下文模块拒绝上下文 |
| `'encode-returned-null'` | 适应者 `encode()` 已返回 `null` |
| `'canceled'` | 一个听众打电话 `preventDefault()` 导航事件 |

### 拦截导航

```ts
framework.event.addEventListener('onContextNavigationNavigate', (event) => {
  console.log('About to navigate:', event.detail.targetURL.pathname);

  // Cancel navigation conditionally
  if (shouldBlock(event.detail)) {
    event.preventDefault();
  }
});
```

## 适配器接口

```ts
interface ContextNavigationAdapter {
  /** Unique identifier for logging and diagnostics. */
  id: string;
  /** Return `true` if this adapter handles the given app/URL combination. */
  canHandle(ctx: AdapterResolutionContext): boolean;
  /** Encode context into a URL. Return `null` to skip navigation. */
  encode(args: { context: ContextItem | null; currentURL: URL }): URL | null;
  /** Decode a context ID from a URL. Return `null` if not present. */
  decode(url: URL): string | null;
}

interface AdapterResolutionContext {
  appKey: string;
  appContext: IContextProvider;
  routingStrategy?: 'path' | 'query' | null;
  currentURL: URL;
}
```

## 出口

| 指定者 | 说明 |
| --- | --- |
| `@equinor/fusion-framework-plugin-context-navigation` | 插件运行时间、 配置器、 启用助手、 类型、 事件 |
| `@equinor/fusion-framework-plugin-context-navigation/adapters` | 内建适配工厂(`createPathAdapter`, (中文(简体) ), `createQueryAdapter`, (中文(简体) ), `createCustomAdapter`(中文(简体) ) |
| `@equinor/fusion-framework-plugin-context-navigation/sources` | 来源工厂(`createAppFirstSource`, (中文(简体) ), `createContextFirstSource`)和调节器类型 |
| `@equinor/fusion-framework-plugin-context-navigation/utils` | URL 工具函数 |

## 同伴依赖关系

| 软件包 | 目的 |
| --- | --- |
| `@equinor/fusion-framework-module` | 基本单元合同 |
| `@equinor/fusion-framework-module-app` | 应用程序切换和实例加载 |
| `@equinor/fusion-framework-module-context` | 国家管理 |
| `@equinor/fusion-framework-module-navigation` | URL 导航 |
| `@equinor/fusion-framework-module-event` | 事件发送 |
| `rxjs` | 反应流 |

## 另见

-   [`@equinor/fusion-framework-module-context`](https://npmcn.com/package/modules/context/) 查询、验证和解析的背景模块
-   [`@equinor/fusion-framework-module-app`](https://npmcn.com/package/modules/app/) ——应用模块定义 `FrameworkOptions.contextRouting` 在建筑列表中

## 常见问题

### @equinor/fusion-framework-plugin-context-navigation 是什么？

基于适应器的合并框架门户上下文与URL调和器

### 如何安装 @equinor/fusion-framework-plugin-context-navigation？

在项目目录运行 npm install @equinor/fusion-framework-plugin-context-navigation，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：rxjs（^7\.8\.1）、@equinor/fusion-framework-module（^6\.2\.0）、@equinor/fusion-framework-module-app（^8\.3\.0）、@equinor/fusion-framework-module-event（^6\.1\.4）、@equinor/fusion-framework-module-context（^9\.1\.0）、@equinor/fusion-framework-module-navigation（^8\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @equinor/fusion-framework-plugin-context-navigation 支持 TypeScript 吗？

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

### @equinor/fusion-framework-plugin-context-navigation 支持 ESM 还是 CommonJS？

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

### @equinor/fusion-framework-plugin-context-navigation 可以商用吗？

@equinor/fusion-framework-plugin-context-navigation 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @equinor/fusion-framework-plugin-context-navigation 的下载量有多少？

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

### @equinor/fusion-framework-plugin-context-navigation 还在维护吗？

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

