路由
简单路由案例
1、命令创建项目
ng new angualrdemo04 复制代码
执行该命令时,会有这么一段内容询问你是否需要创建路由。
Would you like to add Angular routing? (y/N) 复制代码
输入 y 便可给项目中增加路由设置,新建的项目文件结构如下:
查看 app-routing.module.ts 文件内容:
import {NgModule} from '@angular/core'; import {Routes, RouterModule} from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } 复制代码
接着我们创建几个组件。
2、创建组件
ng g component components/product ng g component components/news ng g component components/home 复制代码
3、在 app-routing.module.ts 配置路由,根据不同的 URL, 跳转到不同的页面
import {NewsComponent} from './components/news/news.component'; import {HomeComponent} from './components/home/home.component'; import {ProductComponent} from './components/product/product.component'; const routes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'news', component: NewsComponent }, { path: 'product', component: ProductComponent } ]; 复制代码
4、app.component.html 根组件模板,配置 router-outlet 显示动态加载的路由
<header class="header"> <a [routerLink]="[ '/home' ]" routerLinkActive="active">首页</a> <a [routerLink]="[ '/news' ]" routerLinkActive="active">新闻</a> <a [routerLink]="[ '/product' ]" routerLinkActive="active-link">商品</a> </header> <router-outlet></router-outlet> 复制代码
5、app.component.css 配置样式
.header{ height: 44px; line-height: 44px; background-color: black; } .header a{ color: #ffffff; padding: 10px 40px; } .header .active { color: red; } .header .active-link{ color: orange; } 复制代码
6、页面测试
7、小结
routerLink 里面用到的 path 就是在 app-routing.module.ts 里配置的,routerLinkActive 作用是当此链接指向的路由激活时,该指令就会往宿主元素上添加一个 CSS 类。
<router-outlet></router-outlet>
可以简单把它理解为: 页面的占位符,动态加载,会被替换掉的。
当点击 home、about、 dashboard 时, 在导航栏的下方,会被对应的 XX.component.html 替换掉。
关于 <router-outlet>
的讲解可以参看: 干什么用的?
默认路由
当启动项目时,会默认打开链接 http://localhost:4200/ ,但是该页面没有任何信息,因此我们设置该链接默认打开 home 页面。
在 app-routing.module.ts 配置默认路由,以下两种配置方式都可以,但是必须在最后位置。
const routes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'news', component: NewsComponent }, { path: 'product', component: ProductComponent }, { path: '**', component: HomeComponent // path: '**', redirectTo: 'home' } ]; 复制代码
还有一种方式,配置可以在任意位置,个人习惯放在首位。
const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' } { path: 'home', component: HomeComponent }, { path: 'news', component: NewsComponent }, { path: 'product', component: ProductComponent } ]; 复制代码
重定向路由需要一个 pathMatch
属性,来告诉路由器如何用 URL 去匹配路由的路径,否则路由器就会报错。 在本应用中,路由器应该只有在完整的 URL等于 ''
时才选择 HeroListComponent
组件,因此要把 pathMatch
设置为 'full'
。
动态路由
对于上文中的 news 组件,我们新建一个 news-detail 组件,用来显示新闻详情。
1、配置动态路由
const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'news', component: NewsComponent }, { path: 'newsDetail/:id', component: NewsDetailComponent }, { path: 'product', component: ProductComponent }, ]; 复制代码
2、news.component.ts
nums: any[] = []; constructor() { } ngOnInit(): void { for (let i = 0; i < 10; i++) { this.nums.push('这是第' + i + '条新闻'); } } 复制代码
3、news.component.html
<p>news works!</p> <ul> <li *ngFor="let item of nums, let key = index"> --> <!-- <a [routerLink]="['/newsDetail',key]" >{{key}} ---- {{item}}</a> --> <a routerLink="/newsDetail/{{key}}" >{{key}} ---- {{item}}</a> </li> </ul> 复制代码
上述两种链接方式都是正确的,routerLink="xxxx",表示静态链接,另一种则表示动态链接,可以通过动态值来生成链接。
4、在 news-detail.component.ts 获取动态路由的值
import {ActivatedRoute} from '@angular/router'; export class NewsDetailComponent implements OnInit { constructor(public router: ActivatedRoute) { } ngOnInit(): void { this.router.params.subscribe((data) => { console.log(data); }); } } 复制代码
5、页面测试
动态路由的JS跳转
普通跳转
1、同新建 NewsDetail 组件一样,再新建一个 ProductDetail 组件。
2、product.component.html
<button (click)="getProduct()">js跳转到商品详情页面</button> <button (click)="getHome()">js跳转到主页面</button> 复制代码
3、product.component.ts
import { Router } from '@angular/router'; export class ProductComponent implements OnInit { constructor(public router: Router) { } getProduct() { this.router.navigate(['/productDetail/', '123']); } getHome() { this.router.navigate(['/home']); } } 复制代码
3、页面测试
get传值
1、product.component.html
<button (click)="getNews()">js关于get传值</button> 复制代码
2、在 product.component.ts 额外引入 NavigationExtras
import {Component, OnInit} from '@angular/core'; import {Router, NavigationExtras} from '@angular/router'; export class ProductComponent implements OnInit { constructor(public router: Router) { } getNews() { let params: NavigationExtras = { queryParams: { 'aid': '123' } }; this.router.navigate(['/news'],params); } } 复制代码
3、在 news 组件中获取 get 传值
constructor(public router: ActivatedRoute) { console.log(this.router.queryParams); } 复制代码
4、页面测试
父子路由
在网上冲浪时可以经常看到点击头部页面按钮,主页会
1、新建组件
ng g component components/home ng g component components/home/welcome ng g component components/home/setting ng g component components/product ng g component components/product/pcate ng g component components/product/plist 复制代码
2、配置路由
import {HomeComponent} from './components/home/home.component'; import {ProductComponent} from './components/product/product.component'; import {WelcomeComponent} from './components/home/welcome/welcome.component'; import {SettingComponent} from './components/home/setting/setting.component'; import {PcateComponent} from './components/product/pcate/pcate.component'; import {PlistComponent} from './components/product/plist/plist.component'; const routes: Routes = [ { path: 'home', component: HomeComponent, children:[ { path:'welcome',component:WelcomeComponent }, { path:'setting',component:SettingComponent }, { path:'**',component:WelcomeComponent } ] }, { path: 'product', component: ProductComponent, children:[ { path:'pcate',component:PcateComponent }, { path:'plist',component:PlistComponent }, { path:'**',component:PlistComponent } ] }, { path: '**', component: HomeComponent } ]; 复制代码
3、app.component.html
<header class="header"> <a [routerLink]="[ '/home' ]" routerLinkActive="active">首页</a> <a [routerLink]="[ '/product' ]" routerLinkActive="active">商品</a> </header> <router-outlet></router-outlet> 复制代码
4、home.component.html
<div class="content"> <div class="left"> <a [routerLink]="['/home/welcome']" >欢迎首页</a> <br> <br> <a [routerLink]="['/home/setting']" >系统设置</a> </div> <div class="right"> <router-outlet></router-outlet> </div> </div> 复制代码
5、style.css
.content{ width: 100%; height: 400px; display: flex; } .left{ padding: 20px 20px; width: 200px; border-right: 1px black solid; height: 400px; } .right{ flex: 1px; } 复制代码
6、页面测试
7、小结
根据测试结果可知,当点击按钮进行页面跳转时,页面不需要刷新,网址发生改变即可。
模块
自定义模块
Angular 内置模块
当我们项目比较小的时候可以不用自定义模块。 但是当我们项目非常庞大的时候把所有的组件都挂载到根模块里面不是特别合适。 所以这个时候我们就可以自定义模块来组织我们的项目。
添加自定义模块
接下来我们新建一个项目 angularDemo07,然后添加自定义模块。
ng g module module/user //如果需要添加路由,则在新建模块时执行下面命令。 ng g module module/user --routing ng g component module/user 复制代码
查看上图可以发现,user 模块和项目自带的 app 模块结构一致,只是少了路由配置文件。接着我们在 user 模块中新建组件。
添加自定义模块下的组件
ng g component module/user/components/profile ng g component module/user/components/address ng g component module/user/components/order 复制代码
新建完成的项目结构如图所示:
我们查看 user.module.ts 文件内容:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { UserComponent } from './user.component'; import { ProfileComponent } from './components/profile/profile.component'; import { AddressComponent } from './components/address/address.component'; import { OrderComponent } from './components/order/order.component'; @NgModule({ declarations: [UserComponent, ProfileComponent, AddressComponent, OrderComponent], imports: [ CommonModule ] }) export class UserModule { } 复制代码
如果想要访问 user 组件,必须要在 user 模块中将该组件暴露出来。修改 user.module.ts 文件:
@NgModule({ // user模块里的组件 declarations: [UserComponent, ProfileComponent, AddressComponent, OrderComponent], // 暴露组件,让其被其他模块所访问 exports: [UserComponent], imports: [ CommonModule ] }) 复制代码
然后在根模块中引入 user 模块。
import {UserModule} from './module/user/user.module'; imports: [ BrowserModule, AppRoutingModule, UserModule ], 复制代码
最后在 app.component.html 文件中添加 user 组件,即可看到 user.component.html 中的内容。
<h2>app组件</h2> <app-user></app-user> 复制代码
假设想要访问 user 模块下的 order 组件,则必须先将其暴露,才可以在 app.component.html 中访问。
添加自定义模块下的服务
ng g service module/user/services/common 复制代码
然后在 user 模块中引入该服务。
import {CommonService} from './services/common.service'; providers:[CommonService] 复制代码
同理我们再创建一个 product 模块,以及它下面的组件。
ng g module module/product --routing ng g component module/product ng g component module/product/components/plist ng g component module/product/components/pinfo 复制代码
路由配置
通过配置路由,可以实现懒加载,从而不必在 app.module.ts 文件中引入自定义模块,就可以访问自定义模块下的组件内容。
1、首先在 app-routing.module.ts 文件中配置路由
const routes: Routes = [ // { path: 'user', loadChildren: './module/user/user.module#UserModule'}, // 更改路径无效 // { path: 'user', loadChildren: 'src/app/module/user/user.module#UserModule'}, { path: 'user', loadChildren: () => import('./module/user/user.module').then(m => m.UserModule) }, // { path: 'product', loadChildren: './module/product/product.module#ProductModule' } // { path: 'product', loadChildren: 'src/app/module/product/product.module#ProductModule' } { path: 'product', loadChildren: () => import('./module/product/product.module').then(m => m.ProductModule) } ]; 复制代码
2、在自定义模块中配置路由
const routes: Routes = [ { path: '', component: UserComponent }, { path: 'profile', component: ProfileComponent }, { path: 'address', component: AddressComponent }, { path: 'order', component: OrderComponent } ]; 复制代码
问题记录
自定义模块路由配置懒加载时报错
错误信息如下:
EXCEPTION: Uncaught (in promise): Error: Cannot find module 'app/home/home.module' 复制代码
解决办法:
const routes: Routes = [ // { path: 'user', loadChildren: './module/user/user.module#UserModule'}, // 更改路径无效 // { path: 'user', loadChildren: 'src/app/module/user/user.module#UserModule'}, { path: 'user', loadChildren: () => import('./module/user/user.module').then(m => m.UserModule) }, // { path: 'product', loadChildren: './module/product/product.module#ProductModule' } // { path: 'product', loadChildren: 'src/app/module/product/product.module#ProductModule' } { path: 'product', loadChildren: () => import('./module/product/product.module').then(m => m.ProductModule) } ];