在Angular中,什么是'pathmatch:full',它有什么作用?

GCJ*_*ghe 74 typescript angular

在这里它使用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 { }
Run Code Online (Sandbox Code Playgroud)

Avi*_*ius 80

虽然技术上是正确的,但其他答案将从对 Angular 的 URL-to-route 匹配的解释中受益。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 段的前缀。但是,路由器只能匹配full segment,这使得这个命名有点混乱。

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

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,
          },
        ],
      },
    ],
  },
];
Run Code Online (Sandbox Code Playgroud)

请注意,Route此处的每个对象都使用默认匹配策略,即prefix. 这一战略意味着在整个配置树,并尝试将路由器通过迭代来匹配它的目标URL逐段直到URL是完全匹配的。下面是这个例子的实现方式:

  1. 遍历根数组,寻找第一个 URL 段的精确匹配 - users
  2. 'products' !== 'users',所以跳过那个分支。请注意,我们使用的是相等性检查而不是.startsWith().includes()- 只有完整的段匹配计数!
  3. :other匹配任何值,所以它是一个匹配。然而,目标 URL 还没有完全匹配(我们仍然需要匹配jamesarticles),因此路由器会寻找孩子。
  • 的唯一孩子:othertricks,也就是!== 'james',因此不是匹配项。
  1. Angular 然后回溯到根数组并从那里继续。
  2. 'user' !== 'users,跳过分支。
  3. '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,
        },
      ],
    },
  ],
}
Run Code Online (Sandbox Code Playgroud)

注意 的用法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,
    },
  ],
}
Run Code Online (Sandbox Code Playgroud)

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,
        },
      ],
    },
  ],
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下:

  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,
      },
    ],
  },
];
Run Code Online (Sandbox Code Playgroud)

对于我们的初始 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,
      },
    ],
  },
];
Run Code Online (Sandbox Code Playgroud)
  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,
  },
];
Run Code Online (Sandbox Code Playgroud)

假设我们正在尝试访问/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',
  },
];
Run Code Online (Sandbox Code Playgroud)

如果我们导航到根 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,
  },
];
Run Code Online (Sandbox Code Playgroud)

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


小智 77

RouterModule.forRoot([
      { path: 'welcome', component: WelcomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', component: 'pageNotFoundComponent' }
    ])
Run Code Online (Sandbox Code Playgroud)

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

如果https://开头本地主机:4200/乱码,这将重定向到,因为通配符的pageNotFound屏幕(路径:"**")

案例2 - pathMatch:'prefix':

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


Par*_*ain 71

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

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

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

pathMatch = 'full' 表示整个URL路径需要匹配并由路由匹配算法使用.

pathMatch = 'prefix' 表示选择路径与URL开头匹配的第一条路径,但是路由匹配算法继续搜索其余URL匹配的匹配子路由.


小智 6

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

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

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

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

  • 在我看来,这个解释(在给出的解释中)是最简单、最容易理解的。 (2认同)