145

在这里它使用完整的路径匹配,当我删除这个路径匹配时,它甚至不会加载应用程序或运行项目

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';

import { AppComponent }  from './app.component';
import { WelcomeComponent } from './home/welcome.component';

/* Feature Modules */
import { ProductModule } from './products/product.module';

@NgModule({
  imports: [
    BrowserModule,
    HttpModule,
    RouterModule.forRoot([
      { path: 'welcome', component: WelcomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', redirectTo: 'welcome', pathMatch: 'full' }
    ]),
    ProductModule
  ],
  declarations: [
    AppComponent,
    WelcomeComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
4

6 回答 6

140
RouterModule.forRoot([
      { path: 'welcome', component: WelcomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', component: 'pageNotFoundComponent' }
    ])

案例 1 pathMatch:'full':在这种情况下,当应用程序在localhost:4200(或某些服务器)上启动时,默认页面将是欢迎屏幕,因为 url 将是https://localhost:4200/

如果这会因为通配符https://localhost:4200/gibberish而重定向到pageNotFound屏幕path:'**'

案例2 pathMatch:'prefix'

如果路由有 { path: '', redirectTo: 'welcome', pathMatch: 'prefix' },现在这将永远不会到达通配符路由,因为每个 url 都会匹配path:''定义。

于 2018-09-24T14:18:33.993 回答
103

虽然在技术上是正确的,但其他答案将受益于对 Angular 的 URL-to-route 匹配的解释。我不认为你可以完全(原谅双关语)理解pathMatch: full如果你不知道路由器首先是如何工作的。


让我们首先定义一些基本的东西。我们将使用此 URL 作为示例:/users/james/articles?from=134#section.

  1. 这可能很明显,但让我们首先指出查询参数 ( ?from=134) 和片段 ( #section) 在路径匹配中没有任何作用。只有基本 url ( /users/james/articles) 很重要。

  2. Angular 将 URL 分割成。的段/users/james/articles当然usersjamesarticles

  3. 路由器配置是具有单个根节点的树结构。每个Route对象都是一个节点,它可能有children节点,而这些节点又可能有其他children节点或叶节点。

路由器的目标是找到一个路由器配置分支,从根节点开始,它将完全匹配 URL 的所有 (!!!)段。这很关键!如果 Angular 没有找到可以匹配整个URL 的路由配置分支——不多也不少——它不会渲染任何东西

例如,如果您的目标 URL 是/a/b/c,但路由器只能匹配/a/b/a/b/c/d,则不匹配,应用程序将不会呈现任何内容。

最后,具有 的路线的redirectTo行为与常规路线略有不同,在我看来,它们将是任何人真正想要使用的唯一地方pathMatch: full。但我们稍后会谈到这一点。

默认 ( prefix) 路径匹配

该名称背后的原因prefix是这样的路由配置将检查配置path的是否是剩余 URL 段的前缀。但是,路由器只能匹配完整的段,这使得这个命名有点混乱。

无论如何,假设这是我们的根级路由器配置:

const routes: Routes = [
  {
    path: 'products',
    children: [
      {
        path: ':productID',
        component: ProductComponent,
      },
    ],
  },
  {
    path: ':other',
    children: [
      {
        path: 'tricks',
        component: TricksComponent,
      },
    ],
  },
  {
    path: 'user',
    component: UsersonComponent,
  },
  {
    path: 'users',
    children: [
      {
        path: 'permissions',
        component: UsersPermissionsComponent,
      },
      {
        path: ':userID',
        children: [
          {
            path: 'comments',
            component: UserCommentsComponent,
          },
          {
            path: 'articles',
            component: UserArticlesComponent,
          },
        ],
      },
    ],
  },
];

请注意,这里的每个Route对象都使用默认匹配策略,即prefix. 这种策略意味着路由器会遍历整个配置树,并尝试逐段将其与目标 URL 进行匹配,直到URL完全匹配。以下是此示例的完成方式:

  1. 遍历根数组,寻找与第一个 URL 段完全匹配的 - users
  2. 'products' !== 'users',所以跳过那个分支。请注意,我们使用的是相等检查而不是.startsWith().includes()- 只有完整段匹配计数!
  3. :other匹配任何值,所以它是匹配的。但是,目标 URL 还没有完全匹配(我们仍然需要匹配jamesarticles),因此路由器会寻找孩子。
  • :otheris的唯一孩子tricks,即!== 'james',因此不匹配。
  1. Angular 然后回溯到根数组并从那里继续。
  2. 'user' !== 'users,跳过分支。
  3. 'users' === 'users- 段匹配。但是,这还不是完全匹配,因此我们需要寻找孩子(与步骤 3 相同)。
  • 'permissions' !== 'james', 跳过它。
  • :userID匹配任何东西,因此我们有一个匹配的james段。然而这仍然不是完全匹配,因此我们需要寻找一个匹配的孩子articles
    1. 我们可以看到它:userID有一个子路由articles,这给了我们一个完整的匹配!因此应用程序呈现UserArticlesComponent.

完整的 URL ( full) 匹配

示例 1

现在想象一下,users路由配置对象看起来像这样:

{
  path: 'users',
  component: UsersComponent,
  pathMatch: 'full',
  children: [
    {
      path: 'permissions',
      component: UsersPermissionsComponent,
    },
    {
      path: ':userID',
      component: UserComponent,
      children: [
        {
          path: 'comments',
          component: UserCommentsComponent,
        },
        {
          path: 'articles',
          component: UserArticlesComponent,
        },
      ],
    },
  ],
}

注意 的用法pathMatch: full。如果是这种情况,步骤 1-5 将是相同的,但步骤 6 会有所不同:

  1. 'users' !== 'users/james/articles- 段不匹配,因为路径配置userspathMatch: full完整 URL 不匹配,即users/james/articles.
  2. 由于没有匹配,我们跳过了这个分支。
  3. 至此,我们在没有找到匹配项的情况下完成了路由器配置。该应用程序不呈现任何内容

示例 2

如果我们有这个怎么办:

{
  path: 'users/:userID',
  component: UsersComponent,
  pathMatch: 'full',
  children: [
    {
      path: 'comments',
      component: UserCommentsComponent,
    },
    {
      path: 'articles',
      component: UserArticlesComponent,
    },
  ],
}

users/:userIDpathMatch: full仅匹配,users/james因此它再次不匹配,并且应用程序不呈现任何内容。

示例 3

让我们考虑一下:

{
  path: 'users',
  children: [
    {
      path: 'permissions',
      component: UsersPermissionsComponent,
    },
    {
      path: ':userID',
      component: UserComponent,
      pathMatch: 'full',
      children: [
        {
          path: 'comments',
          component: UserCommentsComponent,
        },
        {
          path: 'articles',
          component: UserArticlesComponent,
        },
      ],
    },
  ],
}

在这种情况下:

  1. 'users' === 'users- 段匹配,但james/articles仍然不匹配。让我们寻找孩子。
  • 'permissions' !== 'james'- 跳过。
  • :userID'只能匹配单个段,即james. 但是,它是一个pathMatch: full路由,它必须匹配james/articles(整个剩余的 URL)。它无法做到这一点,因此它不匹配(所以我们跳过这个分支)!
  1. 同样,我们没有找到任何匹配的 URL,应用程序没有呈现任何内容

您可能已经注意到,pathMatch: full配置基本上是这样说的:

忽略我的孩子,只匹配我。如果我自己无法匹配所有剩余的URL 段,请继续。

重定向

任何Route定义了 a 的redirectTo都将根据相同的原则与目标 URL 进行匹配。此处唯一的区别是,只要匹配,就会应用重定向。这意味着如果重定向路由使用默认prefix策略,则部分匹配足以导致重定向。这是一个很好的例子:

const routes: Routes = [
  {
    path: 'not-found',
    component: NotFoundComponent,
  },
  {
    path: 'users',
    redirectTo: 'not-found',
  },
  {
    path: 'users/:userID',
    children: [
      {
        path: 'comments',
        component: UserCommentsComponent,
      },
      {
        path: 'articles',
        component: UserArticlesComponent,
      },
    ],
  },
];

对于我们的初始 URL ( /users/james/articles),会发生以下情况:

  1. 'not-found' !== 'users'- 跳过它。
  2. 'users' === 'users'- 我们有一场比赛。
  3. 这个匹配有一个redirectTo: 'not-found'立即应用
  4. 目标 URL 更改为not-found
  5. 路由器再次开始匹配并立即找到匹配not-found项。应用程序呈现NotFoundComponent.

现在考虑如果users路线也有会发生什么pathMatch: full

const routes: Routes = [
  {
    path: 'not-found',
    component: NotFoundComponent,
  },
  {
    path: 'users',
    pathMatch: 'full',
    redirectTo: 'not-found',
  },
  {
    path: 'users/:userID',
    children: [
      {
        path: 'comments',
        component: UserCommentsComponent,
      },
      {
        path: 'articles',
        component: UserArticlesComponent,
      },
    ],
  },
];
  1. 'not-found' !== 'users'- 跳过它。
  2. users将匹配 URL 的第一段,但路由配置需要full匹配,因此跳过它。
  3. 'users/:userID'匹配users/jamesarticles仍然不匹配,但这条路线有孩子。
  • articles我们在孩子们身上找到了一个匹配项。整个 URL 现在已匹配并且应用程序呈现UserArticlesComponent.

空路径 ( path: '')

空路径是一种特殊情况,因为它可以匹配任何而不“消耗”它(因此它的孩子必须再次匹配该段)。考虑这个例子:

const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'users',
        component: BadUsersComponent,
      }
    ]
  },
  {
    path: 'users',
    component: GoodUsersComponent,
  },
];

假设我们正在尝试访问/users

  • path: ''将始终匹配,因此路由匹配。然而,整个 URL 还没有被匹配——我们仍然需要匹配users
  • 我们可以看到有一个 child users,它匹配剩余的(也是唯一的!)段,我们有一个完整的匹配。应用程序呈现BadUsersComponent.

现在回到最初的问题

OP使用了这个路由器配置:

const routes: Routes = [
  {
    path: 'welcome',
    component: WelcomeComponent,
  },
  {
    path: '',
    redirectTo: 'welcome',
    pathMatch: 'full',
  },
  {
    path: '**',
    redirectTo: 'welcome',
    pathMatch: 'full',
  },
];

如果我们导航到根 URL ( /),路由器将如何解决这个问题:

  1. welcome不匹配空段,所以跳过它。
  2. path: ''匹配空段。它有一个pathMatch: 'full',这也很满意,因为我们匹配了整个 URL(它有一个空段)。
  3. 重定向到welcome发生并且应用程序呈现WelcomeComponent.

如果没有pathMatch: 'full'呢?

实际上,人们会期望整个事情的行为完全相同。但是,Angular 明确禁止这样的配置 ( { path: '', redirectTo: 'welcome' }),因为如果你把它放在Route上面welcome,理论上它会创建一个无限循环的重定向。所以 Angular 只是抛出一个错误,这就是应用程序根本无法工作的原因!( https://angular.io/api/router/Route#pathMatch )

实际上,这对我来说没有太大意义,因为 Angular实现了针对这种无休止重定向的保护——每个路由级别只运行一个重定向!这将停止所有进一步的重定向(如下例所示)。

怎么样path: '**'

path: '**'绝对匹配任何af/frewf/321532152/fsa带有或不带有pathMatch: 'full'.

此外,由于它匹配所有内容,因此还包括根路径,这{ path: '', redirectTo: 'welcome' }在此设置中完全是多余的。

有趣的是,拥有这样的配置是非常好的:

const routes: Routes = [
  {
    path: '**',
    redirectTo: 'welcome'
  },
  {
    path: 'welcome',
    component: WelcomeComponent,
  },
];

如果我们导航到/welcome,path: '**'将是一个匹配项,并且会重定向到 Welcome。从理论上讲,这应该会启动一个无休止的重定向循环,但 Angular 会立即停止(因为我之前提到的保护)并且整个事情都很好。

于 2020-06-19T18:50:49.127 回答
101

pathMatch = 'full'当 URL 匹配的其余不匹配段是前缀路径时,导致路由命中

pathMatch = 'prefix'当剩余的 URL重定向路由的前缀路径开头时,告诉路由器匹配重定向路由。

参考:https ://angular.io/guide/router#set-up-redirects

pathMatch: 'full'意味着,整个 URL 路径需要匹配并被路由匹配算法消耗。

pathMatch: 'prefix'意味着,选择路径与 URL 开头匹配的第一个路由,但随后路由匹配算法将继续搜索与 URL 其余部分匹配的匹配子路由。

于 2017-03-24T05:44:32.710 回答
7

路径匹配策略,“前缀”或“完整”之一。默认为“前缀”。

默认情况下,路由器从左侧检查 URL 元素以查看 URL 是否与给定路径匹配,并在匹配时停止。例如,'/team/11/user' 匹配 'team/:id'。

路径匹配策略 'full' 匹配整个 URL。在重定向空路径路由时这样做很重要。否则,因为空路径是任何 URL 的前缀,即使导航到重定向目标,路由器也会应用重定向,从而创建无限循环。

来源:https ://angular.io/api/router/Route#properties

于 2020-05-06T13:56:42.490 回答
0

Angular 的默认行为是:所有路由的 {pathMatch: 'prefix'}。

现在,让我们看看两者之间有什么区别:

如果 pathMatch: 'prefix' => Angular 将在路由数组中搜索路径的前缀(在 URL 中)。

如果 pathMatch: 'full' => Angular 将在 routes 数组中搜索确切的路径(在 URL 中)。

于 2021-10-20T07:45:11.417 回答
-1

想象以下网址:

example.com/main/anything.
  • 案例 1中,它将重定向到 ErrorPage。

  • 案例 2中,它将重定向到 MainPage。


案例 1:(我们将 pathMatch 定义为 'full')

const routes: Routes = [
  {path: '', component: MainPageComponent},
  {path: 'main', redirectTo: '', pathMatch: 'full'},
  {path: '**', component: ErrorPageComponent}
];

案例2:(我们没有定义pathMatch,默认是pathMatch: 'prefix')

const routes: Routes = [
  {path: '', component: MainPageComponent},
  {path: 'main', redirectTo: ''},
  {path: '**', component: ErrorPageComponent}
];
于 2021-11-05T11:19:10.987 回答