在角度上,什么是“路径匹配: 完全”,它有什么影响?

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

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 { }
187721 次浏览

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

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

档号: https://angular.io/guide/router#set-up-redirects

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

pathMatch: 'prefix'的意思是,选择路径与 URL 开始匹配的第一条路径,然后路由匹配算法继续搜索与其余 URL 匹配的子路由。

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 返回文章页面

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

路径匹配策略,其中一个是“前缀”或“全部”。默认是“前缀”。

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

路径匹配策略“ full”匹配整个 URL。在重定向空路径路由时,这样做非常重要。否则,由于空路径是任何 URL 的前缀,路由器甚至在导航到重定向目的地时也会应用重定向,从而创建一个无止境的循环。

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

虽然技术上是正确的,其他的答案将受益于 Angular 的 URL 到路由匹配的解释。如果你一开始就不知道路由器是如何工作的,我认为你不能完全理解 pathMatch: full是做什么的。


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

  1. 这可能是显而易见的,但让我们首先指出,查询参数(ABC0)和片段(#section)在路径匹配中不起任何作用。只有基地址(/users/james/articles)的问题。

  2. 角分裂的网址到 片段。片段的 /users/james/articles,当然是,usersjamesarticles

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

路由器的目标是找到一个从根节点开始的路由器配置 树枝,它将匹配 URL 的 完全正确(! ! !)段。如果角没有找到一个路由配置分支,可以匹配 整个的 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',因此不匹配。
  1. 角度然后回溯到根数组,并继续从那里。
  2. 'user' !== 'users跳过树枝。
  3. 段匹配。但是,这还不是完全匹配,因此我们需要寻找子级(与步骤3相同)。
  • 跳过 'permissions' !== 'james'
  • :userID匹配任何东西,因此我们有一个匹配的 james段。然而,这是 还是不完全匹配,因此我们需要寻找一个孩子,将匹配 articles
    1. 我们可以看到 :userID有一个子路由 articles,这给了我们一个完整的匹配!因此,应用程序呈现 UserArticlesComponent

完整 URL (full)匹配

例子一

现在想象一下 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匹配,因为带有 pathMatch: full的路径配置 users与完整的 URL (即 users/james/articles)不匹配。
  2. 既然没有匹配,我们就跳过这个分支。
  3. 此时,我们到达了路由器配置的末尾,但是没有找到匹配的路由器。

例子2

如果我们用这个代替呢:

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

带有 pathMatch: fullusers/:userID只匹配 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. 片段匹配,但是 james/articles仍然不匹配。让我们寻找孩子。
  • 跳过。
  • :userID'只能匹配一个片段,即 james。但是,它是一个 pathMatch: full路由,并且它必须匹配 james/articles(剩余的所有 URL)。它不能这样做,因此它不匹配(所以我们跳过这个分支) !
  1. 同样,我们未能找到任何匹配的 URL 和应用程序呈现 没什么

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

无视我的孩子,只配我。如果我自己不能匹配所有的 剩下的 URL 段,那么继续。

重定向

任何定义了 redirectToRoute都将根据相同的原则与目标 URL 进行匹配。唯一的区别是 当 < strong > 段 匹配时应用重定向。这意味着,如果重定向路由使用默认的 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. 跳过。
  2. 找到匹配了。
  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. 跳过。
  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
  • 我们可以看到有一个子 users,它匹配其余的(并且只匹配!)我们有一个完整的匹配。应用程序呈现 BadUsersComponent

现在回到最初的问题

运营商使用这种路由器配置:

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之上,理论上它会创建一个无穷无尽的重定向循环。所以角度只是 抛出一个错误,这就是为什么应用程序将不工作在所有!(https://angular.io/api/router/Route#pathMatch)

实际上,这对我来说没有太大的意义,因为角 还有已经实现了对这种无休止的重定向的保护-它只运行一个单一的重定向每个路由级别!这将停止所有进一步的重定向(正如您将在下面的示例中看到的)。

path: '**'呢?

path: '**' 将与 什么都行匹配(af/frewf/321532152/fsa是匹配) ,有或没有 pathMatch: 'full'

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

有趣的是,拥有这种配置完全没有问题:

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

如果我们导航到 /welcomepath: '**'将是一个匹配和重定向到欢迎将发生。从理论上讲,这应该开始一个无休止的重定向循环,但 Angular 立即停止(因为我前面提到的保护) ,整个工作正常。

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

Now, let's see what is the difference between the two:

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

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