首页 > 解决方案 > 基于服务结果的动态路径

问题描述

我正在使用 Angular 8 创建一个 WordPress 主题。

我想允许用户从 WP Dashboard 中选择一个自定义的永久链接结构。

注意:这不是 WP 问题。我只是为那些熟悉它的人提到 WP 以便能够更好地理解这个问题。对于那些不熟悉它的人来说,永久链接结构基本上是一组规则,用友好的 url 显示 WP 内容。

如果用户可以选择自定义永久链接结构,我必须设置动态路由设计,以便 Angular 应用程序相应地工作。

所以,一个可能被称为customRoutesSvc的服务(它真的需要是一个服务吗?)将连接到一个数据库并获取配置,这将是如下所示:

{
 "posts_permalink":"\/%postname%\/",
 "tag_base":"tag",
 "category_base":"category"
}

假设customRoutesSvc现在将这些值作为属性。

所以,我需要以某种方式提供我的路由模块,以考虑该信息。

我的路由模块使用延迟加载,看起来像这样,具有固定的路由路径。

{
  path: 'category/:category',
  loadChildren: () => import('./view-category/view-category.module').then(m => m.ViewCategoryModule)
},
{
  path: 'tag/:tag',
  loadChildren: () => import('./view-tag/view-tag.module').then(m => m.ViewTagModule)
},
{
  path: 'post/:slug',
  loadChildren: () => import('./view-post/view-post.module').then(m => m.ViewPostModule)
}

我在想类似的事情:

{
  path: customRoutesSvc.category_base + 'category/:category',
  loadChildren: () => import('./view-category/view-category.module').then(m => m.ViewCategoryModule)
},
{
  path: customRoutesSvc.tag_base + '/:tag',
  loadChildren: () => import('./view-tag/view-tag.module').then(m => m.ViewTagModule)
},
{
  path: '**',
  loadChildren: () => import('./view-post/view-post.module').then(m => m.ViewPostModule)
}

请注意,最后一条路线将吸收所有内容,然后 view-post 模块将处理其余部分并显示帖子或重定向到错误页面。

为什么我有这个问题?

据我了解,Angular 在服务之前加载 Angular 模块。不是因为任何偏好,而是因为服务是捆绑到 Angular 模块中的 ES2015 模块。这意味着:Angular 需要它的 Angular 模块来知道要加载哪些 ES2015 模块(组件、服务、管道……)。因此,Angular 路由模块在服务之前加载,因此服务无法与模块本身通信。

到目前为止我尝试了什么?

我试着思考并得到答案。

请不要解释我是来求代码的。这更像是一个概念性问题,其目的不是为了代码答案,而是为了帮助我继续靠自己的理论答案。

我认为唯一可能的解决方案是什么?

由于服务无法与路由模块通信(这是真的吗?),我需要使用一条吸收所有内容的单一路径创建父路由(**)。

然后我需要有一个 DispatchComponent 来分析该 url 并将其与有关永久链接结构的现有信息进行比较。

最后,我需要 DispatchComponent 将内容重定向到正确的最终组件,该组件将负责提供结果。

如果这是解决方案,我如何通过延迟加载来实现这一点,以及一个组件如何在 Angular 实际呈现 HTML 模板之前将其渲染任务委托给另一个组件?我不能在这里使用重定向,因为那只会再次重新启动路由问题。

请随时要求对我的目的进行说明。谢谢你。

标签: angularrouting

解决方案


我认为您正在寻找的是动态路由。这是一个可悲的未充分记录的功能,但您实际上可以在运行时修改路由器的配置,例如在获取您的数据库配置的订阅中customRoutesSvc

  constructor(private router: Router) {
    router.resetConfig({
      // A new routes object like the one you supply in the routing module.
    });
    // It's also possible to manipulate the config object directly.
    router.config.unshift({ path: 'page1', component: Page1Component });
  }

因此,您认为服务无法与路由器通信的假设是错误的。您可以拥有一个包含解析器的全部路由,该解析器可获取数据库配置、重置路由器配置并根据新配置将路由器重新导航到相同位置。

路由模块路由:

const routes: Routes = [
  { path: '**', component: DummyComponent, resolve: {routing: RoutingResolve}}
];

路由解析器:

import { Injectable } from '@angular/core';
import { Router, ActivatedRouteSnapshot, RouterStateSnapshot, Resolve} from '@angular/router';

@Injectable()
export class RoutingResolve implements Resolve<any> {

  constructor(private router: Router, private routes: customRoutesSvc ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any>|any {
    let config = this.routes.getRoutingStructure();
    this.router.resetConfig(config);
    this.router.navigate(route.url);
  }
}

由于配置现在被其他东西取代,包罗万象的路线已经消失,而是我们在 Angular 应用程序中自由导航,直到硬刷新重新初始化应用程序。


推荐阅读