在Angular中,什么是“路径匹配:完整”,它有什么作用?


101

在这里它是完整使用pathmatch的,当我删除此pathmatch时,它甚至不会加载应用程序或运行项目

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 { }

Answers:


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

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

如果由于通配符而https://localhost:4200/gibberish将其重定向到pageNotFound屏幕path:'**'

情况2 pathMatch:'prefix'

如果这些路由具有 { path: '', redirectTo: 'welcome', pathMatch: 'prefix' },则由于每个URL都将匹配path:''定义的URL,因此它将永远不会到达通配符路由。


您好,谢谢您对本示例的清楚解释,但是您能否给出另一个示例来说明其他路线,以使其完全清楚?(例如使用带有子路线等的示例。)。谢谢
sohaieb

确实很不错,但是您能告诉我如何用2种不同的布局进行配置。例如内部布局和外部布局>
Kapil索尼

87

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

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

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

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

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


24

尽管在技术上是正确的,但其他答案将从对Angular的URL到路由匹配的解释中受益。我不认为您一开始不了解pathMatch: full路由器的工作原理,您完全无法理解。


让我们首先定义一些基本的东西。我们将以以下网址为例:/users/james/articles?from=134#section

  1. 显而易见,但是首先让我们指出查询参数(?from=134)和片段(#section)在路径匹配中不起作用。仅基本网址(/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),因此路由器会寻找子代。
    • 唯一的孩子:other就是tricks,这是!== 'james',因此不匹配。
  4. 然后,Angular返回到根数组并从那里继续。
  5. 'user' !== 'users,跳过分支。
  6. 'users' === 'users-细分匹配。但是,这还不是完全匹配,因此我们需要寻找孩子(与第3步相同)。
    • 'permissions' !== 'james', 跳过它。
    • :userID匹配任何东西,因此我们有一个匹配james段。但是,这仍然不是完全匹配,因此我们需要寻找一个匹配的孩子articles
      1. 我们可以看到其中:userID有一条子路线articles,这给了我们一个完整的比赛!因此,应用程序呈现UserArticlesComponent

完整网址(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)。它无法做到这一点,因此不是匹配项(因此我们跳过此分支)!
  2. 同样,我们找不到与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,
  },
];

如果我们导航到/welcomepath: '**'将是一个匹配项,并且将发生重定向到welcome。这应该会启动一个无限循环的重定向,但是Angular会立即停止该重定向,并且整个过程都可以正常工作。


3

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

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

路径匹配策略“完整”与整个URL匹配。重定向空路径路由时,执行此操作很重要。否则,因为空路径是任何URL的前缀,所以路由器即使在导航到重定向目标时也将应用重定向,从而造成无限循环。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.