>  기사  >  웹 프론트엔드  >  Angular4의 라우터 사용에 대한 자세한 설명

Angular4의 라우터 사용에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-04-08 17:35:263457검색

이번에는 Angular4 라우터 사용 방법에 대해 자세히 설명하겠습니다. Angular4 라우터 사용 시 주의 사항은 무엇입니까?

라우팅이라고도 알려진 라우터는 프런트엔드에서 비교적 중요한 개념입니다. 특정 주소와 해당 페이지는 라우터를 통해 연결되고 분리되어 분리 목적을 달성합니다. src/app 디렉터리에 새 디테일 폴더를 생성하고 gundam-detail.comComponent라는 파일을 생성합니다.

import { Component } from '@angular/core';
import { Gundam } from '../../model/gundam';
@Component({
  template: `
    <p *ngIf="selectedGundam">
    <span>{{selectedGundam.name}}</span>
    <span>{{selectedGundam.type}}</span>
    </p>
  `
})
export class GundamDetailComponent {
    selectedGundam: Gundam;
}

ps: 이름 지정에 관해서는 기본적으로 xxx+"-"+"비즈니스 유형"+"컴포넌트 유형"의 이름 지정 방법이 사용됩니다. 적어도 공식 문서에서는 이것이 권장됩니다. 물론 구성 요소 이름을 Zhutou San으로 지정할 수도 있지만 표준 이름을 지정하면 구성 요소의 가독성이 높아질 수 있습니다. 임의의 관리자 이름을 지정하는 것이 마음에 들지 않더라도 오랫동안 동일한 코드 조각을 리팩터링하지 않을 것이라고 확신할 수 있는 사람은 아무도 없습니다. 그러므로 여전히 친절해야 합니다. 댓글은 안 써도 괜찮습니다. 좀 더 표준화된 이름을 붙이는 게 낫습니다.

ps2: 하도급 방식과 관련하여 어떤 사람들은 뷰와 컨트롤러를 함께 묶은 다음 논리에 따라 더 세분화하는 것을 좋아하며 어떤 사람들은 반대 방향으로 논리를 먼저 나눈 다음 뷰를 나눕니다. 그리고 컨트롤러. 이에 대해 통일된 결론은 없는 것 같습니다. 저는 개인적으로 후자의 방법을 선호하므로 이번 프로젝트에서는 후자의 방법을 채택합니다.

현재 파일에는 아무것도 없습니다. app.comComponent.ts에서 사원을 옮기기만 하면 됩니다.

먼저 요구 사항을 명확히 한 다음 라우터 작성을 시작하세요.

요구 사항: 건담 목록 페이지에서 항목을 클릭하면 건담 세부 정보 페이지로 이동합니다.

Angular 컴포넌트로서 페이지에서 라우터를 사용하려면 먼저 app.module.ts에서 선언해야 합니다.

ps: 이전 사업은 app.module.ts와 아무런 관련이 없지만 이것이 중요하지 않다는 의미는 아닙니다. app.module.ts는 전체 프로젝트를 조정하고 관리하는 android의 mainifist 파일과 동일합니다.

app.module.ts 열기:

  1. imports: 구성 요소 페이지에서 기본 클래스를 사용합니다.

  2. 선언: 기존 사용자 정의 구성 요소 선언.

  3. bootstrap: 프로젝트가 시작될 때부터 들어가는 컴포넌트인 안드로이드의 메인 런칭으로 이해하시면 됩니다.

라우터를 사용하기 전에 import를 해야 합니다:

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

RouterModule의 forRoot 메소드를 호출해야 하기 때문에, RouterModule.forRoot는 프로젝트에서 사용하는 기본 클래스이므로 imports로 작성해야 합니다.

 imports: [
  BrowserModule,
  FormsModule,
  RouterModule.forRoot()
 ],

RouterModule.forRoot는 두 개의 매개변수를 허용합니다. 첫 번째 매개변수는 점프를 나타내는 경로 배열입니다. 두 번째 매개변수는 항상 무시됩니다.

라우트 클래스에는 경로와 구성 요소라는 두 가지 주요 속성이 포함되어 있습니다. 경로에 액세스하면 고유한 구성 요소를 찾을 수 있습니다.

forRoot에 홈 페이지와 세부 정보 페이지라는 두 가지 구성 요소가 포함된 경로 배열을 추가하세요.

RouterModule.forRoot([
  {
    path: '',
    component: AppComponent
  },
  {
    path: '',
    component: GundamDetailComponent
  }
])

app.module.ts는 이제 다음과 같습니다:

import {
NgModule
} from '@angular/core';
import {
BrowserModule
} from '@angular/platform-browser';
import {
FormsModule
} from '@angular/forms';
import { RouterModule }  from '@angular/router';
import {
AppComponent
} from './component/appcomponent/app.component';
import { GundamDetailComponent } from './component/detail/gundam-detail.component';
@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot([
      {
        path: '',
        component: AppComponent
      },
      {
        path: '',
        component: GundamDetailComponent
      }
      ])
  ],
  declarations: [
    AppComponent,
    GundamDetailComponent
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

두 경로 모두 여전히 비어 있습니다. 아직 중요한 것이 한 가지 누락되어 있고, 작성하더라도 오류가 보고됩니다.

Error : 'AppComponent'를 로드할 기본 아웃렛을 찾을 수 없습니다.

Angular에서는 라우터가 router-outlet 라벨과 함께 사용됩니다. 즉, 라우터는 표시할 구성 요소를 결정하고 라우터 아웃렛은 이를 표시할 위치를 결정합니다.

라벨

<router-outlet></router-outlet>

app.comComponent.ts

의 템플릿에 추가하면 예상대로 2개의 홈페이지가 표시됩니다. 페이지,Angular는 먼저 부트스트랩에서

app.comComponent.ts

에 들어가서 인터페이스(즉, 라우터 출력 위 부분)를 렌더링했습니다. 라우터를 다시 찾으러 갔더니 해당 라우터에도 구성품이 있어서 다시 로드해봤습니다.

所以为了正常显示,也要把主页也单独抽出来。所有组件通过app.component.ts里的来进行加载。而app.component.ts作为整个demo的最外层容器可以进行一些公共的操作(典型:后退动作)。

在src下新建host包,新建gundam-host.component.ts文件。
基本上可以把整个app挪过来,删除掉out标签,删掉selector(暂时用不到)。

import {
Component
} from '@angular/core';
import { Gundam } from '../../model/gundam';
import { GUNDAMS } from './../../service/data';
@Component({
  template: `
    <p *ngFor="let gundam of gundams" (click)="onSelected(gundam)">
      <span>
        {{gundam.name}}
      </span>
    </p>
  `
})
export class GundamHostComponent {
  gundam: Gundam = {
    name: '海牛',
    type: 'NewType'
  };
  gundams = GUNDAMS;
  selectedGundam: Gundam; // 定义一个selectedGudam作为展示详情的变量
  onSelected (gundam: Gundam): void {
    this.selectedGundam = gundam; // 通过参数赋值
  }
}

app.component.ts只保留标签,其他一概去掉。

修改app.module.ts文件,导入gundam-host.component.ts并把GundamHostComponent 增加到组件声明declarations里。

修改route里的path所指向的component,默认进入后显示主页组件:

before

 

after

path的值为”(空字符串)的表示不需要增加子路径。

修改详情页的路径:

{
  path: 'detail',
  component: GundamDetailComponent
}

在主页里增加跳转连接:

点击跳转(路径已改变)

现在点击主页的高达列表的item后,可以跳转到一个空白的详情页。之所以是空白,是因为详情页的值是需要由主页进行传递的。现在主页详情页分家以后,需要通过路由来进行值传递。

传值的方法有很多种,甚至可以传的值也有很多种。
目前我先用最笨的方法:将gundam类转化为一个字符串,将字符串传递到详情页面后再转化为gundam类。

在app.component.ts文件的class里添加函数:

parseGundamToString(gundam: Gundam): string {
  return gundam.name + '&' + gundam.type;
} // 将gundam类转化为固定格式的字符串

修改app.component.ts文件的template,访问gundam路径时转化传递转化过的gundam字符串

<p *ngFor="let gundam of gundams" routerLink="/detail/name=parseGundamToString(gundam)">
  <span>
  {{gundam.name}}
  </span>
</p>

修改详情页的path

{
  path: 'detail/:gundam',
  component: GundamDetailComponent
}

/:gundam 是一个占位符,又是参数说明。表示传递过来的参数属性是gundam。

这样在detail文件中,就可以从url的连接中拿到传递过来的高达字符串。

获得这个字符串的时机,应该是在在detail页面初始化的时候。Angular提供了所谓的的“钩子”(hook),用来标示component的活动周期—其实也就是是类似于Android里onStart或者onCreate一样的方法。

gundam-detail.component.ts的中添加OnInit钩子,或者说接口:

import { Component, OnInit } from '@angular/core';

在class后面加implements关键词和OnInit来实现该接口:

export class GundamDetailComponent implements OnInit {
  selectedGundam: Gundam ;
  ngOnInit(): void {
  }
}

剩下的事情,就是读取连接上传来的参数就可以了。

读取连接上传递的参数还是要用到router里的几个类,所以需要在detail里导入。

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

导入完成后,通过在构造器里注入的方式进行调用:

(有关注入,现在暂时没有说到)

constructor(
private route: ActivatedRoute){}

angular会自动创建ActivatedRoute的实例。

先在ngOnInit里输出看看params是什么

this.route.params.switchMap((params: Params) => console.log(params))

ps:switchMap是angular官方给的拿取url参数的方法,也是需要预先导入才可以使用:

import 'rxjs/add/operator/switchMap';

ps2: 有关箭头函数

(params: Params) => this.gundamStr = params['gundam']

是一个箭头函数,等同于

function(params){
  this.gundamStr = params['gundam']
}

其中params是switchMap的返回值,返回的即是通过路由连接传递过来的参数所在的类。

ps3: 箭头函数真的是整个ES6里最恶心的东西,之一。

控制台中 输出:

传递过来的参数,是一个gundam类格式化输出的字符串,所以还要在detail里补充一个反格式化字符串到gundam类的函数。

parseStringToGundam(str: string): Gundam {
  const temp = str.split('&');
  const tempGundam: Gundam = {
  name: temp[0],
  type: temp[1]
  };
  return tempGundam;
}

最终,获得detail的初始化是这个样子的

ngOnInit(): void {
  this.route.params // 通过注入的方式拿到route里的参数params
  .switchMap((params: Params) => this.gundamStr = params['gundam']) // 通过参数拿到gundam字符串并付给detail里的一个临时变量
  .subscribe(() => this.selectedGundam = this.parseStringToGundam(this.gundamStr)); // 通过反格式化函数解析临时变量并返回给作为显示的model
}

移动web页面间传值确实没有什么太好的方法,angular和react都是如此。以前我们的做法是短的参数直接挂连接传走,长的大的或者object的参数就先保存本地,然后第二个页面再从本地读取。

但是像android那样扔一个intent里直接就过去了的方式,确实没有。

回首页:

 

点击一个列表:

 

包结构:

 

总的来说,业务被分开了,结构干净多了。虽然现在还体现不出来,但是写到后来就觉得心花怒放,磨刀不误砍柴工功啊。

作为router,也可以分离的。

目前我的项目里只有2个页面,如果多起来-比如20来个,那么app.module.ts又会变的乱七八糟。

所以要把router也给扔出去。

新建一个文件app-routing.module.ts,然后把footRoot平移过来(带上引用)。

在app-routing.module.ts文件里,也需要ngModul。个人理解ngModul就相当于一个基类指示器,导出class后以便被其他类引用。

import {
NgModule
} from '@angular/core';
import { RouterModule }  from '@angular/router';
import { GundamDetailComponent } from './component/detail/gundam-detail.component';
import { GundamHostComponent } from './component/host/gundam-host.component';
@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: '',
        component: GundamHostComponent
      },
      {
        path: 'detail/:id',
        component: GundamDetailComponent
      }
    ])
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

然后既然已经有了这个类,可以导入到app.module.ts里使用使得整个文件看起来清爽一些。

import {
NgModule
} from '@angular/core';
import {
BrowserModule
} from '@angular/platform-browser';
import {
FormsModule
} from '@angular/forms';
import {
AppComponent
} from './component/appcomponent/app.component';
import { GundamDetailComponent } from './component/detail/gundam-detail.component';
import { GundamHostComponent } from './component/host/gundam-host.component';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule // 调用路由
  ],
  declarations: [
    AppComponent,
    GundamDetailComponent,
    GundamHostComponent
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

当然,官方文档又进行了进一步简化。

既然forRoot是一个Route数组,那么数组也可以单独抽出来,当然进一步抽取也可以放到另一个文件里。

import {
NgModule
} from '@angular/core';
import { RouterModule, Route }  from '@angular/router';
import { GundamDetailComponent } from './component/detail/gundam-detail.component';
import { GundamHostComponent } from './component/host/gundam-host.component';
const routes: Route[] = [
  {
    path: '',
    component: GundamHostComponent
  },
  {
    path: 'detail/:gundam',
    component: GundamDetailComponent
  }
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

我个人比较偷懒,就先抽取到这一步。

现在连主页面和详情页面都被分开了,项目的耦合度又进一步降低。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

webpack的4.0打包优化如何实现

怎样把字符串转为json字符串

위 내용은 Angular4의 라우터 사용에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.