AoT 和函数工厂(动态路由模板)

AoT and function factory (Dynamic Route Templates)

我正在尝试建立一个 UrlMatcher 工厂

export const dummyMatcher: UrlMatcher = matchUrlFn(sitemap as any, 'dummy');

export const routes: Routes = [
  { matcher: dummyMatcher, component: DummyComponent },
  { path: '**', component: DummyComponent },
];

但这不适用于 AoT...我们如何使用 AoT 处理函数工厂?

我试过了

export function dummyMatcher(): UrlMatcher { return routeMatcher(sitemap as any, 'dummy'); }

但是编译器在抱怨:

Type '{ matcher: () => UrlMatcher; component: typeof DummyComponent; }...' is not assignable to type 'Route[]'.


用例:

我需要匹配网页(在 NavigationNode[] 中描述)并在特定的模板组件中呈现它们。页面可以有多个 url(用于迁移目的、本地化 url 等)。 匹配逻辑如下:

import { UrlSegment, UrlSegmentGroup, Route, UrlMatchResult } from '@angular/router';
import { inArray } from '@core/utils';

export interface NavigationNode {
  ...
  title?: string;
  template?: string;
  urls?: string[];
}

/**
 * https://angular.io/api/router/UrlMatcher
 */
export const UrlMatcherFactory = (conditions) =>
  (segments: UrlSegment[], group: UrlSegmentGroup, route: Route): UrlMatchResult =>
    conditions(segments) ? ({ consumed: segments }) : null;

export const matchUrl = (nodes: NavigationNode[], template?: string) =>
  (segments: UrlSegment[]) => nodes
    .filter(node => template ? node.template === template : true)
    .some(node => inArray(node.urls)(`/${segments.join('/')}`));

export const matchUrlFn= (nodes: NavigationNode[], template?: string) =>
  UrlMatcherFactory(matchUrl(nodes, template));

这可以很容易地扩展到使用不同的匹配,例如正则表达式:

export const matchRegex = (nodes: NavigationNode[]) =>
  (segments: UrlSegment[]) => nodes
    .some(node => /\w+\/xyz/\d{1, 3}/.test(node.title)); /* bad example (: */

export const matchRegexFn = (nodes: NavigationNode[], template?: string) =>
  UrlMatcherFactory(matchRegex(nodes));

matcher 属性 应该实现 UrlMatcher 类型:

export declare type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) => UrlMatchResult;

所以我建议您更改代码,例如:

export function dummyMatcher(segments: UrlSegment[], group: UrlSegmentGroup, route: Route): UrlMatchResult {
  const factory = matchUrlFn(sitemap as any, 'dummy');
  return factory(segments, group, route);
}

对于面临 AOT 编译器问题的新手 你需要将 fat arrow 函数移动到普通的 ES5 函数 & export 它(即使你不在其他任何地方使用它)

移动这个

const routes: Routes = [
  {
    component: SomeComponent,
    matcher: () => { //your url matcher },
  }
,...
];

export function yourUrlMatcher( //params ) { //your function here }

const routes: Routes = [
  {
    component: SomeComponent,
    matcher: yourUrlMatcher,
  }
,...
];