Angular 路由(app-routing)之初体验

前言待会再续,先进入主题吧

如果你试图进入Angular官网学习Routes,那丰富的属性只会让你望而却步,越读越懵。不如咱们从最简单的开始,一点点剖析Angular的路由模块吧。

最常见的路由配置

使用route对象的pathcomponent属性,偶尔用到redirectpatchMatch,或许你就已经能够胜任很多场景下的路由跳转了。 首先我们在新建一个Angular项目时,ng new my-first-router 时,CLI会自动问你是否需要为你添加路由模块,输入y即可

如果你记忆超群,不如记一下下面的命令行,直接一步到位 ng new my-first-router --routing,这样做的好处就是生成一个app-routing.module.ts的文件,并且自动import到AppModule上。

在开始之前,让我们清空一下app.component.html文件,仅留下最后一行的<router-outlet></router-outlet>

现在打开我们的app-routing.module.ts文件,找到下面这行代码:

js 复制代码
const routes: Routes = [];

这将是我们接下来的主战场,下面我们来设想几个场景,我将以本地项目为例子:

  1. 假设我们默认启动的项目URL为localhost:4200,但是我的主页面路径为localhost:4200/home,有什么办法让用户输入localhost:4200就能自动跳转到home路径吗?

    :使用redirectTo,即当路径匹配的时候重定向到redirectTo指定的路径:

js 复制代码
const routes: Routes = [{
  path: '',
  redirectTo: 'home',
  pathMatch: 'full'
},
{
  path: 'home',
  component: HomeComponent
}];

解析 : 'localhost:4200'后面没有任何字符,所以我们用path:''去匹配,一旦匹配上,就将url改成'localhost:4200/home',随后路径中的home字符串又匹配上了path:'home',因此在AppComponent Html文件中的<router-outlet>标签里将会出现HomeComponent中的内容。(注意:文中提到的component请自行通过ng g component xxx生成,就不重复描述了),请注意上段代码的第四行 patchMatch:'full'这个是必须要的,后面会详细解释,咱们先留个小疑问。(挖坑)

  1. 如果我输入了一个没有匹配上的路径,会发生什么?如何控制它呢?
    :当输入一个不存在的路径时,系统会自动重定向到项目原始路径"localhost:4200",如果想捕捉这类未匹配的路径我们可以巧用通配符path:"**"去匹配一切路径,做一个兜底方案。
js 复制代码
const routes: Routes = [{
  path: '',
  redirectTo: 'home',
  pathMatch: 'full'
},
{
  path: 'home',
  component: HomeComponent
},
{
  path: '**',
  component: NotFoundComponent
}
];

试图在浏览器中输入localhost:4200/testPath,你会看到not-found works!的字样,说明NotFoundComponent被加载显示了,path:'**'捕捉到了testPath路径。

但是使用上面的通配符,切记一点需要把它放在所有的路径配置的最下面,因为Angular是从上往下去匹配路径的,一旦匹配上**就直接去NotFound了,下面配置的所有路径都不再生效啦,切记切记!

有了上面的基础知识,其实一级路径都可以轻松配置啦。但是二级路径又要如何配置呢?

配置子路由 Children属性

children属性其实也是一个Routes对象,所以上面说到的属性也可以重复使用。假设我有一个ParentComponentFirstChildComponentSecondChildComponentParent中有Section A是我无论如何都要显示的,Section B则是根据路由控制的,例如'parent/first-child'路径下,我想在Section B中显示 first-child works!'parent/second-child'路径下我则想显示second child works! 该怎么去配置这个路由呢?

当你想要通过路由控制某一个部位的显示内容的时候,首先在该部位放入<router-outlet></router-outlet>

parent.component.html 复制代码
<!--Section A-->
<p>parent works!</p> 

<!--Section B-->
<router-outlet></router-outlet>

然后在app-routing.module.ts文件中加入下面片段:

js 复制代码
...
{ 
  path: 'parent',
  component: ParentComponent,
  children: [
    {
    path: 'first-child',
    component: FirstChildComponent
    },{
    path: 'second-child',
    component: SecondChildComponent  
    }
  ]
},
...

运行结果:

一个简单有效的子路由就实现啦! 关于子路由后面还有懒加载之类的知识,先不在这里多阐述了,有机会再慢慢整理。

详细讲一下pathMatch

当你有了子路由的知识以后,我就可以引入pathMatch的概念了,该属性在Angular官方文档中是这样说的 路径匹配策略,为 "prefix" 或 "full" 之一。默认为"prefix"。再往后的内容无论中英文版本我都读不懂,就不再贴出来了。我开始试图理解这个属性,很明显prefix是前缀的意思,full肯定是它的反之,我结合官方文档中蹩脚的解释猜测,是不是设置成prefix的路径,只要是前半段符合,则自动匹配上;而设置成full的则必须完全匹配; 我试图用localhost:4200/homeTestlocalhost:4200/home/test 去验证我的想法,很不幸我都被带到了not-found页面,说明他们都没有被 {path:'home', pathMatch:'prefix'*默认值*} 捕捉到。

再次研读一下官网信息,有一句话给了我启发例如,如果路由的子项(children)之一与段"user"匹配,则认为"/team/11/user"与前缀"team/:id"匹配。

也就是说team/:id被认为是prefix前缀。当解析/team/11/user时,由于/team/11符合前缀team/:id,因此angular引擎会继续进入该路径的children属性中查找是否有匹配user的子路由,一旦找到,路由即匹配成功。一切似乎变的合理起来。下面只需要写个例子证明这一猜想,我将创建PathMatchComponent, PrefixComponent,在pathMatch.component.html中放置<router-outlet></router-outlet>, 并且设置以下路由参数:

js 复制代码
...
{
  path: 'pathMatch',
  component: PathMatchComponent,
  children:[
    {
      path: 'prefix',
      component: PrefixComponent
    }
  ],
  pathMatch: 'prefix' /**默认值 */
},
...

运行结果:

到这里其实并没有特别,就是一个简单的子路由实现,但是当你试图将patchMatch改成full,你会发现not-found页面出现了,至此patchMatch之谜终于揭开了。用我自己的话解释就是,这个字段决定了当前定义的这个route里的路径path是否支持片段式匹配,即一个路径/pathMatch/prefix是否可以通过前缀匹配先进入到path:'pathMatch'一级路由中,再去它的children二级路由中查找剩下的'/prefix'路径,当然如果还是没找到匹配项的话,依然会被not-found捕捉到。但如果我们设置pathMatch:'full',则表示不支持二级路由匹配,必须在当前路由中直接找到匹配的path。这就是为啥上面的例子一旦改成full模式,/pathMatch/prefix 不再完全匹配path:'patchMatch',因此被判别为无匹配路由,从而进入not-found。

如果你真正的理解了pathMatch,或许你就能明白为什么下面的路径强调必须要开启full模式了吧?(填坑)

js 复制代码
const routes: Routes = [{
  path: '',
  redirectTo: 'home',
  pathMatch: 'full'
},

因为任何的路径我们都可以认为是path:''的子路由,如果还是允许前缀匹配的话,任何路由都会被path:''捕捉再被redirectTo属性带走,谁也别想去自己的路径配置里去。(统统毁灭吧!--发疯文学 :p)

至此,一个简单的Angular Routes算是解释清楚了,其他的属性我们留到下一篇吧~

相关推荐
汪子熙12 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
汪子熙1 天前
Angular 客户端渲染时,从 ng-state 里读取 SSR 状态的具体逻辑
前端·javascript·angular.js
汪子熙2 天前
关于 Angular SSR 应用 html 源代码中的 ng-state script 标签
javascript·html·angular.js
汪子熙2 天前
Angular ng-state script 元素的生成机制介绍
前端·javascript·angular.js
@AfeiyuO3 天前
Angular基础学习(入门 --> 入坑)
前端·angular.js
汪子熙5 天前
什么是 Angular 的 @HostBinding 注解
前端·javascript·angular.js
zsy_19916 天前
Angular Content security policy
javascript·ecmascript·angular.js
汪子熙6 天前
什么是 Angular 开发中的 Dumb components
前端·javascript·angular.js
笃励6 天前
Angular面试题十
前端·javascript·angular.js
百锦再9 天前
Angular与Vue的全方位对比分析
前端·javascript·vue.js·前端框架·angular.js