Skip to content

RouterPlugin

路由器插件接口,参考 Swiper.js 插件架构设计。每个插件通过 install 方法注册 hook 到 PluginContext,路由器在导航流程的各个阶段依次调用已注册的 hook。

类型定义

ts
interface RouterPlugin {
  /** 插件名称 */
  name: string
  /**
   * 安装插件
   * @param context - 插件上下文,用于注册 hook
   * @param options - 路由器初始化选项(插件可读取自己的选项)
   */
  install(context: PluginContext, options: RouterOptions): void
}

内置插件

插件name说明
ParamsPlugin'params'页面参数传递(params/persistent),详见导航 - params
AnimationPlugin'animation'导航动画(App 端),详见导航 - 动画
ChannelPlugin'channel'页面间通信 + usePageChannel(),详见导航 - 通信
InterceptorPlugin'interceptor'拦截 uni 原生导航 API,详见拦截器机制

注册方式

createRouter()plugins 选项中注册:

ts
import { createRouter, ParamsPlugin, AnimationPlugin, ChannelPlugin, InterceptorPlugin } from '@meng-xi/uni-router'

const router = createRouter({
  routes: [...],
  plugins: [ParamsPlugin, AnimationPlugin, ChannelPlugin, InterceptorPlugin],
  // 插件对应的选项
  paramsPersistent: true,      // 需要 ParamsPlugin
  useUniEventChannel: true,    // 需要 ChannelPlugin
  interceptUniApi: true        // 需要 InterceptorPlugin
})

PluginContext

插件上下文,路由器暴露给插件的 hook 注册接口。

ts
interface PluginContext {
  /** 在 matcher.resolve() 前增强原始路由位置 */
  onEnrichLocation(hook: (location: RouteLocationRaw) => RouteLocationRaw): void

  /** resolve 之后、守卫之前,从增强后的路由位置中提取插件数据 */
  onAfterResolve(hook: (enrichedLocation: RouteLocationRaw, pluginData: Record<string, any>) => void): void

  /** uni API 调用前,修改导航 URL query 和选项 */
  onPrepareNavigation(hook: (ctx: NavigationPrepareContext) => void): void

  /** uni API 调用成功后,扩展 NavigationResult */
  onCompleteNavigation(hook: (ctx: NavigationCompleteContext) => void): void

  /** 导航中止或失败时,执行清理操作 */
  onNavigationAbort(hook: (pluginData: Record<string, any>) => void): void

  /** syncCurrentRoute 期间,从 URL query 中提取插件数据 */
  onRouteSync(hook: (query: Record<string, string>, params: Record<string, any>) => void): void

  /** router.install() 被调用时触发 */
  onAppInstall(hook: (app: App) => void): void

  /** 当前路由位置(只读) */
  readonly currentRoute: RouteLocation

  /** 解析路由位置为完整的 RouteLocation 对象 */
  resolve(location: RouteLocationRaw): RouteLocation

  /** 路由器实例引用 */
  readonly router: Router

  /** 核心 ParamsManager 实例 */
  readonly paramsManager: ParamsManager

  /** 检查指定插件是否已注册 */
  hasPlugin(name: string): boolean
}

导航准备上下文,在 uni API 调用前由插件使用:

ts
interface NavigationPrepareContext {
  /** 目标路由 */
  to: RouteLocation
  /** 来源路由 */
  from: RouteLocation
  /** 导航模式 */
  mode: 'push' | 'replace' | 'relaunch' | 'back'
  /** 插件间共享数据 */
  pluginData: Record<string, any>
  /** 实际导航 URL 的 query(可变) */
  query: Record<string, string>
  /** uni 导航选项(可变) */
  options: UniNavigationOptions
}

导航完成上下文,在 uni API 调用成功后由插件使用:

ts
interface NavigationCompleteContext {
  /** 目标路由 */
  to: RouteLocation
  /** 导航模式 */
  mode: 'push' | 'replace' | 'relaunch' | 'back'
  /** 插件间共享数据 */
  pluginData: Record<string, any>
  /** 原生 eventChannel(仅 push 模式可用) */
  nativeEventChannel?: EventChannel
  /** 导航结果(可变:插件扩展) */
  result: Record<string, any>
}

自定义插件示例

ts
import type { RouterPlugin, PluginContext } from '@meng-xi/uni-router'
import type { RouterOptions } from '@meng-xi/uni-router'

const AnalyticsPlugin: RouterPlugin = {
  name: 'analytics',

  install(context: PluginContext, options: RouterOptions) {
    // 导航完成后上报
    context.onCompleteNavigation((ctx) => {
      trackPageView(ctx.to.path, ctx.mode)
    })

    // 导航中止时上报
    context.onNavigationAbort(() => {
      trackEvent('navigation_aborted')
    })
  }
}

// 注册
const router = createRouter({
  routes: [...],
  plugins: [AnalyticsPlugin]
})

下一步

Released under the MIT License.