Angular 中间部分 2.3 路由

来源:互联网 发布:手机大字体软件 编辑:程序博客网 时间:2024/06/07 02:20

路由

Angular路由包括:基础路由,路由策略,路由参数,Auth,login,子路由

基础&安装

anchor tag
页面指定内容快速访问
在html设定<a name="about"><h1>About</h1></a>
访问http://something/#about即可到h1tag

Angular 有如下配置路由
- Routes 这个应用支持的路由
- RouterOutlet 路由和对应的内容
- RouterLink 连接路由

导入 route 模块 p220,p243

import {  RouterModule,  Routes} from '@angular/router';

app.module.ts定义路由

const routes: Routes = [  // 普通路由  { path: '', redirectTo: 'home', pathMatch: 'full' },  { path: 'home', component: HomeComponent },  { path: 'about', component: AboutComponent },  // 认证路由  { path: 'login', component: LoginComponent },  {    path: 'protected',    component: ProtectedComponent,    canActivate: [ LoggedInGuard ]  },  // 层叠路由 nested  {    path: 'products',    component: ProductsComponent,    children: childRoutes  }];

path就是路径,component就是对应的组件

redirectTo 就是重定向一个新的路径
访问 http://localhost:4200/#/ 会被重定向到home

同时需要在app.module.ts@NgModule({导入
RouterModule.forRoot(routes)

imports: [    ...    RouterModule.forRoot(routes),     ProductsModule],

RouterOutlet

当改变路由的时候,最好模版的样式不会改变,只是页面的部分内容重新渲染。
**The router-outlet element indicates where the contents of each route component will be
rendered**

定义每一个组件的哪些内容会被渲染

在组件app.component.ts内配置

@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.css']})export class AppComponent {  constructor(private router: Router) {  };}

在html页面

<div class="page-header">  <div class="container">    <h1>Router Sample</h1>    <div class="navLinks">      <a [routerLink]="['/home']">Home</a>      <a [routerLink]="['/about']">About Us</a>      <a [routerLink]="['/contact']">Contact Us</a>      |      <a [routerLink]="['/products']">Products</a>      <a [routerLink]="['/login']">Login</a>      <a [routerLink]="['/protected']">Protected</a>    </div>  </div></div><div id="content">  <div class="container">    <router-outlet></router-outlet>  </div></div>

router-outlet在导航栏的下面,
routerLink指引对应的路由

相比直接设置对应路由:
<a href="/#/home">Home</a>

好处是保持单一页面,而不是重新加载新页面。

put it together

html页面的head

<head>  ...  <base href="/"></head>

包含了路由情况

Angualr通过NgModule的APP_BASE_HREF来配置base而不用直接更改

在NgModule导入APP_BASE_HREF

@NgModule({  providers: [    { provide: LocationStrategy, useClass: HashLocationStrategy },    { provide: APP_BASE_HREF, useValue: '/' }  ]})

先创建3个子组件,在创建父组件连接
p229 p252 父组件设置路由
在app.moudyle.ts导入组件(RouterModule,Routes)
并配置对应的路由

const routes: Routes = [{ path: '', redirectTo: 'home', pathMatch: 'full' },

@NgModule({导入

在html设置对应子组件连接,导航栏,(routerLink,router-outlet)

路由策略 Routing Strategies

默认是PathLocationStrategy,也就是html5默认路由。这个策略下,路由由普通路径组成比如 /home

但同时,HashLocationStrategy也在被使用
但使用HTML5路由时,URL会由普通路径结束。也就是不使用hash/anchor

假设刷新页面时,不会请求根路径,而是/about,但是在服务器端并没有配置,(只配置根路径),会返回404?
所以hTML5默认必须把所有路径都配置。
详细比较见

https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling

HashLocationStrategy使用/#/home

路由参数 /route/:param

当每篇文章都有对应的url id时
/articles/3
/articles/4
需要配置 /route/:param

安装 p235 p258
导入ActivatedRoute

import { ActivatedRoute } from '@angular/router';

设置路由
{ path: 'product/:id', component: ProductComponent },

把ActivatedRoute加入到constructor

export class ProductComponent {  id: string;  constructor(private route: ActivatedRoute)     route.params.subscribe(params => { this.id = params['id']; });  }}

Music search app

P236 P256

Router Hooks login

认证+认证后能访问的内容
P253 P276

AuthService

写AuthService

import { Injectable } from '@angular/core';@Injectable()export class AuthService {  login(user: string, password: string): boolean {    if (user === 'user' && password === 'password') {      localStorage.setItem('username', user);      return true;    }  \\ 当use和password匹配时,返回true,并且储存在localStorage,    return false;  }  logout(): any {    localStorage.removeItem('username');  }  getUser(): any {    return localStorage.getItem('username');  }  isLoggedIn(): boolean {    return this.getUser() !== null;  }}  //provide注入注册export const AUTH_PROVIDERS: Array<any> = [  { provide: AuthService, useClass: AuthService }];

在 login的组件注入

export class LoginComponent {  message: string;  constructor(public authService: AuthService) {    this.message = '';  }  login(username: string, password: string): boolean {    this.message = '';    if (!this.authService.login(username, password)) {      this.message = 'Incorrect credentials.';      setTimeout(function() {        this.message = '';      }.bind(this), 2500);    }    return false;  }  logout(): boolean {    this.authService.logout();    return false;  }}

在login的html

<h1>Login</h1>//认证错误信息<div class="alert alert-danger" role="alert" *ngIf="message">  {{ message }}</div>//使用*ngIf="!authService.getUser()"来认证信息输入<form class="form-inline" *ngIf="!authService.getUser()">  <div class="form-group">    <label for="username">User: (type <em>user</em>)</label>    <input class="form-control" name="username" #username>  </div>  <div class="form-group">    <label for="password">Password: (type <em>password</em>)</label>    <input class="form-control" type="password" name="password" #password>  </div>  <a class="btn btn-default" (click)="login(username.value, password.value)">    Submit  </a></form>//认证成功<div class="well" *ngIf="authService.getUser()">  Logged in as <b>{{ authService.getUser() }}</b>  <a href (click)="logout()">Log out</a></div>

ProtectedComponent p258 p281

只让登入用户访问

创建 logged-in.guard.ts
快速创建Angular内置:

ng generate guard logged-in

/* tslint:disble max-line-length */import { Injectable } from '@angular/core';import {  CanActivate,  ActivatedRouteSnapshot,  RouterStateSnapshot} from '@angular/router';import { Observable } from 'rxjs/Observable';import { AuthService } from './auth.service';@Injectable()export class LoggedInGuard implements CanActivate {  //注入AuthService  constructor(private authService: AuthService) {}  //CanActivate检测authService  canActivate(    next: ActivatedRouteSnapshot,    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {      const isLoggedIn = this.authService.isLoggedIn();      console.log('canActivate', isLoggedIn);      return isLoggedIn;  }}

使用了 CanActivate,并且注入AuthService

配置路由器 p259 p282
在app.module.ts导入AUTH_PROVIDERS和LoggedInGuard

在app.module 认证路由 见开篇路由配置
并provider p260 p283

...  { path: 'login', component: LoginComponent },  {    path: 'protected',    component: ProtectedComponent,    canActivate: [ LoggedInGuard ]  },...providers: [...]

Nested Routes 层叠路由 p264 p287

层叠路由是包含其他路由
主路由->子路由
适用于:网站需要根据每一个用户单独显示对应的信息时。

见开篇路由配置

  {    path: 'products',    component: ProductsComponent,    children: childRoutes  }

products有子参数,
那么在products.module.ts组件中,可以定于自己的路由

export const routes: Routes = [{ path: '', redirectTo: 'main', pathMatch: 'full' },{ path: 'main', component: MainComponent },{ path: 'more-info', component: MoreInfoComponent },]

在组件中

  goToProduct(id: string): void {    this.router.navigate(['./', id], {relativeTo: this.route});  }
原创粉丝点击