【问题标题】:Angular2 Routing Path-Style ParametersAngular2 路由路径样式参数
【发布时间】:2017-09-08 21:32:22
【问题描述】:

使用@angular/router 版本3.0.0-beta.2 我想构建一个允许我的用户浏览文件系统的应用程序。

以下说明了我希望支持的 URL 类型:

http://myapp/browse                   <--- Browse without parameters, lists root dir
http://myapp/browse/animals           <--- Browse "animals" subdirectory
http://myapp/browse/animals/mammals   <--- Browse "animals/mammals" subdirectory

我正在努力想出一种使用RouterConfig 进行配置的机制。


路径样式参数

{ path: 'browse/:path', component: BrowserComponent }

这个RouterConfig 只支持一个子目录,即browse/animals。但是,如果我尝试浏览到子目录 /browse/animals/mammals 的第二级,则会收到以下错误:

Error: Cannot match any routes: '/browse/animals/mammals'

我了解路由器中参数的默认行为(在本例中为 :path)是在第一个正斜杠上“中断”,并假设以下标记是子路径。

如何配置路由器以允许 :path 参数接受正斜杠/“吞噬”整个剩余 URL 作为参数?


可选参数

如何处理用户希望浏览根目录的用例,即 URL /browse。这与上述路由器配置不匹配,因为:path 参数不存在。

我已尝试使用两个不同配置的路由器路径来解决此问题:

{ path: 'browse', component: BrowserComponent },
{ path: 'browse/:path', component: BrowserComponent }

但是,这给我带来了routerLinkActive 的问题。我有一个带有浏览器链接的主菜单,如下所示:

<a [routerLink]="['/browse']" [routerLinkActive]="['active']">...</a>

如果用户浏览到根目录/browse 或某个子目录/browse/animals/,我希望这个主菜单链接具有active 类。

但是,鉴于/browse/animals/ URL 不是/browse 路由的子,它不会变成active

我不能将:path 参数路由作为/browse 根的子路由,因为不需要嵌套视图,这会导致:

Cannot find primary outlet to load BrowserComponent

【问题讨论】:

  • 有什么理由不使用路由器的 beta.2 版本?我不希望这会起作用,但其他几个问题已得到修复。
  • @GünterZöchbauer 不,我没有充分的理由不使用该版本的路由器。我会增加我的依赖。

标签: angular angular2-routing


【解决方案1】:

基于@DaSch 的** 建议,确实可以使用通配符路由:

{ path: '/browse', component: BrowserComponent, children: [ { path: '**' } ] }

没有必要在BrowserComponent 中嵌套router-outlet,因为子路径上没有指定component 字段。

现在将为所有描述的 URL 路由 BrowserComponent:

http://myapp/browse
http://myapp/browse/animals
http://myapp/browse/animals/mammals

现在的挑战是获取代表浏览器导航到的路径的 URL 部分,并在用户导航时订阅更改。

我已经使用Router

router.events.filter(e => e instanceof NavigationEnd)
  .forEach((event: NavigationEnd) => {

    // The root route belongs to "/browse"
    let parentRoot: ActivatedRoute = router.routerState.root.firstChild;
    if (parentRoot.snapshot.url.map(p => p.path).join("/") == "/browse") {

      let path: string = "";

      // Child route is optional, in case the user has browsed to just "/browse"
      let childRoute: ActivatedRoute = parentRoot.firstChild;
      if (childRoute) {
        path = childRoute.snapshot.url.map(p => p.path).join("/");
        console.log("New browser path is ", path);
      }

      this.loadPath(path);
    }
  }
);

【讨论】:

  • 很高兴知道,很好!
  • @jwa 嗨,我正在使用您的代码示例。它真的很完美。谢谢你。我想问你一个关于它的问题。我在共享组件中使用此方法。正如你猜想的那样,我在多个组件中使用它。例如:/browse、/deleted、/shared 等。当我单击另一条路由(使用共享组件)时,this.router.events.observers 的长度正在增加。当我单击完全不同的路由(/foo 没有共享组件)时,它会自行重置(通常 this.router.events.observers 长度为 17)。当我走另一条具有共享组件的路线时,如何防止增加观察者数组的长度?
  • @jwa 好的,我通过订阅解决了它。你能查一下是不是真的吗? this.routerSubscription = router.events.subscribe(event =&gt; { if (event instanceof NavigationEnd) { console.log('bbb'); } }); ngOnDestroy() { this.routerSubscription.unsubscribe(); }
  • 以防万一它对任何人都有帮助:在 Angular 4.1.x 中,我在通配符子项中使用 component 而不是父项:{path: 'browse', children: [{path: '**', component: BrowserComponent}]}。我更喜欢你的版本,但在更改后我遇到了“路由'browse/**'的配置无效。必须提供以下之一:组件、redirectTo、children 或 loadChildren”。由于我以前的版本对我来说也很好用,所以我恢复了我的更改并且没有调查......
【解决方案2】:

我还没有尝试过,但是从文档中,我会尝试使用带有通配符选择器的孩子。

{ path: 'browse', 
  component: ...,
  children: [
     path: '**',
     component: ...
]},

这只是猜测,我必须检查如何检索路径参数以获得给定路径的正确内容。

【讨论】:

  • 那行不通。首先,您在此组件中没有路由器插座,如果您要添加一个,该组件将在我们的组件中再次呈现。
  • 好吧,您可能需要两个不同的组件。这就是细节这只是关于在子路径中使用通配符。
  • @mxii - 完成原型设计后,我可以确认您不需要需要一个新的插座。仅当指定组件时才需要额外的插座。
【解决方案3】:

你可以这样试试..

仅使用您的第一条路线:{ path: 'browse', component: BrowserComponent }

对于文件夹名称使用所谓的optional routes

这里的链接应该有这样的语法:

&lt;a [routerLink]="['/browse', ['f1', 'f2', 'f3', 'f4'] ]"&gt;--link name--&lt;/a&gt;

或者像这样:

&lt;a [routerLink]="['/browse', { folders: ['f1', 'f2', 'f3', 'f4'] } ]"&gt;--link name--&lt;/a&gt;

private _route: ActivatedRoute 注入组件的构造函数并订阅参数:

this._route.params.subscribe(
      val => console.log(val),
      err => console.log(err));

第一个将打印:Object {0: "f1", 1: "f2", 2: "f3", 3: "f4"} 第二个将打印:Object {folders: "f1,f2,f3,f4"}

或者您可能会有另一个想法来使用此optional parameters.. gl 添加您的文件夹! :)

【讨论】:

    【解决方案4】:

    您可以按照https://stackoverflow.com/a/38096260/217408 中的说明动态配置路由器

    router.resetConfig([
     { path: 'team/:id', component: TeamCmp, children: [
       { path: 'simple', component: SimpleCmp },
       { path: 'user/:name', component: UserCmp }
     ] }
    ]);
    

    https://github.com/angular/angular/issues/11437#issuecomment-245995186 提供了一个RC.6 Plunker

    【讨论】:

    • 据我了解,这不是真正的问题。如果我理解他的话,路由本身就是“/browse”,他只有这个组件,但他想把参数放在这种风格的 URL/browse/folder1/folder2/folder3/..../folderN 中。这是不可能的(如果我是对的)..
    • 但他可以重新配置路由器以支持更多参数或添加子路由来获得此行为。我认为使用router.resetConfig 是一种有效的方法。
    【解决方案5】:

    对我来说很有用,router.resetConfig() 在我的应用的自定义逻辑中使用了新的路由规则

    【讨论】:

      猜你喜欢
      • 2017-12-03
      • 2016-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多