为了应对未来的趋势,及时赶上下一趟互联网技术,我最近也在通过具体项目研究angular2,首先必须要吐槽的是,学习angular2的成本本身不高,但是一堆的工具、配置实在让人 很是焦灼,就像asp.net core一样,所有的东西都在向同样的方向迈进:尽量使用已经造好的轮子,而不是自己再弄一个。
当然,统一是好的,但是对于对前端不是太敏感的我来说,还是挑战不小,这就要求我要学好angular2,必须要熟悉一系列的工具链。加油。
今天要说的是一个可以说我遇到的很诡异的问题,我在angular1上进行了相同的尝试,没有发现这个问题,但是在angular2上发现了,我将使用场景还原一下,当然我只是抽取其中的一部分,希望有人遇到或知道如何解决回复一下,当然如果我找到答案,会注明。
背景:我通过angular2 下叫ng2,的路由来实现视图的导航,我使用官方文档英雄列表来说明。我从英雄列表页面通过路由导航到具体的详情页面,但是我准备实现从详情页面导航到列表页面时出现的问题。
我自己尝试了几种实现方式:
- window.history.back():通过浏览器的回退实现
- 通过router.navigate(['/heros']).其中router通过构造函数进行注入
我要说明的问题就是通过第二种实现。
- 步骤1:新建index.html页面,没有什么特别的地方,只是设置了ng2的启动页面
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>guozhiqi</title> 6 <meta name="viewport" content="width=device-width,initial-scale=1"> 7 <link rel="stylesheet" type="text/css" href="node_modules/primeng/resources/themes/delta/theme.css" /> 8 <link rel="stylesheet" type="text/css" href="node_modules/font-awesome/css/font-awesome.css" /> 9 <link rel="stylesheet" type="text/css" href="node_modules/primeng/resources/primeng.min.css" /> 10 <base href="/"> 11 </head> 12 <body> 13 14 <my-app> 15 Loading... 16 </my-app> 17 18 <script src="node_modules/core-js/client/shim.js"></script> 19 <script src="node_modules/reflect-metadata/Reflect.js"></script> 20 <script src="node_modules/zone.js/dist/zone.js"></script> 21 <script src="node_modules/systemjs/dist/system.js"></script> 22 <script src="systemjs.config.js"></script> 23 <script> 24 System.import('app').catch(function (err) { 25 console.error(err); 26 }) 27 </script> 28 29 </body> 30 </html>
- 步骤2:新建app文件夹,并且添加main.ts页面
1 /** 2 * Created by guozhiqi on 2016/9/19. 3 */ 4 import {platformBrowserDynamic}from '@angular/platform-browser-dynamic'; 5 import {AppModule}from './app.module'; 6 import {RouterModule}from '@angular/router'; 7 8 const platform=platformBrowserDynamic(); 9 platform.bootstrapModule(AppModule);
添加ng2的启动模块AppModule
- 在app文件夹添加app.module.ts文件
1 import './rxjs-extensions'; 2 3 import { NgModule } from '@angular/core'; 4 import { BrowserModule } from '@angular/platform-browser'; 5 import { FormsModule } from '@angular/forms'; 6 import { HttpModule } from '@angular/http'; 7 8 // Imports for loading & configuring the in-memory web api 9 import { InMemoryWebApiModule } from 'angular2-in-memory-web-api'; 10 import { InMemoryDataService } from './in-memory-data.service'; 11 12 import { AppComponent } from './app.component'; 13 import { DashboardComponent } from './dashboard.component'; 14 import { HerosComponent } from './heros.component'; 15 import { HeroDetailComponent } from './hero-detail.component'; 16 import { HeroService } from './hero.service'; 17 import { HeroSearchComponent } from './hero-search.component'; 18 import { routing } from './app.routing'; 19 import {RouterModule,Router}from '@angular/router'; 20 21 @NgModule({ 22 imports: [ 23 BrowserModule, 24 FormsModule, 25 HttpModule, 26 InMemoryWebApiModule.forRoot(InMemoryDataService),RouterModule, 27 routing 28 ], 29 declarations: [ 30 AppComponent, 31 DashboardComponent, 32 HeroDetailComponent, 33 HerosComponent, 34 HeroSearchComponent 35 ], 36 providers: [ 37 HeroService 38 ], 39 bootstrap: [ AppComponent ] 40 }) 41 export class AppModule { 42 } 43 44 45 /* 46 Copyright 2016 Google Inc. All Rights Reserved. 47 Use of this source code is governed by an MIT-style license that 48 can be found in the LICENSE file at http://angular.io/license 49 */
重点是我们导入了RoutingModule模块
- 添加路由配置app.routing.ts
1 import {ModuleWithProviders}from '@angular/core'; 2 import {Routes, RouterModule}from '@angular/router'; 3 import {HerosComponent}from './heros.component'; 4 import {DashboardComponent}from './dashboard.component'; 5 import {HeroDetailComponent}from './hero-detail.component'; 6 const appRoutes:Routes = [ 7 { 8 path: 'heros', 9 component: HerosComponent 10 }, 11 { 12 path:'dashboard', 13 component:DashboardComponent 14 }, 15 16 { 17 path:'detail/:id', 18 component:HeroDetailComponent 19 }, 20 { 21 path:'', 22 redirectTo: '/dashboard', 23 pathMatch: 'full' 24 }, 25 { 26 path:'**', 27 component:DashboardComponent 28 } 29 ] 30 31 export const routing:ModuleWithProviders=RouterModule.forRoot(appRoutes);
- 添加英雄列表页面heros.component.ts
1 /** 2 * Created by guozhiqi on 2016/9/19. 3 */ 4 import {Component, OnInit}from '@angular/core'; 5 import {Title}from '@angular/platform-browser'; 6 import {ButtonModule}from 'primeng/primeng'; 7 import {Hero}from './hero'; 8 import {HeroService} from "./hero.service"; 9 import {HeroDetailComponent}from './hero-detail.component'; 10 import {Router}from '@angular/router'; 11 12 @Component({ 13 selector: "my-heros", 14 templateUrl: 'app/heros.component.html', 15 styleUrls: ['app/heros.component.css'] 16 }) 17 18 export class HerosComponent implements OnInit { 19 heros:Hero[]; 20 selectedHero:Hero; 21 22 ngOnInit():void { 23 this.getHeros(); 24 } 25 26 getHeros():void { 27 this.heroService.getHeroes().then(heros=>this.heros = heros); 28 } 29 30 onSelect(hero:Hero) { 31 this.selectedHero = hero; 32 } 33 34 gotoDetail() { 35 this.router.navigate(['/detail', this.selectedHero.id]); 36 } 37 38 add(name:string):void { 39 name = name.trim(); 40 if (!name) { 41 return; 42 } 43 44 this.heroService.create(name) 45 .then(hero=>{ 46 this.heros.push(hero); 47 this.selectedHero=null; 48 }); 49 } 50 51 delete(hero:Hero):void 52 { 53 this.heroService.delete(hero.id) 54 .then(()=>{ 55 this.heros=this.heros.filter(h=>h!==hero); 56 if(this.selectedHero===hero) 57 { 58 this.selectedHero=null; 59 } 60 }) 61 } 62 63 constructor(private router:Router, private titleService:Title, private heroService:HeroService) { 64 this.titleService.setTitle("HeroList"); 65 } 66 67 68 }
重点就出现在我们通过构造函数注入的Router上,我们的英雄列表通过router.navigate(
['/detail', this.selectedHero.id]
)来导航到了详情页面,请注意,router是通过构造函数注入
- 详情页面组件代码
1 /** 2 * Created by guozhiqi on 2016/9/19. 3 */ 4 import {Component, Input, OnInit}from'@angular/core'; 5 import {ActivatedRoute, Params, Router}from'@angular/router'; 6 import {HeroService}from './hero.service'; 7 import {Title}from '@angular/platform-browser'; 8 import {Hero} from "./Hero"; 9 import from = require("core-js/fn/array/from"); 10 11 @Component({ 12 selector: 'my-hero-detail', 13 templateUrl: 'app/hero-detail.component.html', 14 styleUrls: ['app/hero-detail.component.css'], 15 }) 16 17 export class HeroDetailComponent implements OnInit { 18 hero:Hero; 19 currentDate:Date; 20 private router:Router; 21 22 constructor(private heroService:HeroService, 23 private route:ActivatedRoute, 24 router:Router, 25 private title:Title) { 26 this.currentDate = new Date(); 27 28 this.title.setTitle("hero-detail"); 29 } 30 31 ngOnInit():void { 32 this.route.params.forEach((params:Params)=> { 33 let id = +params['id']; 34 this.heroService.getHero(id).then(hero=>this.hero = hero); 35 }); 36 } 37 38 goBack():void { 39 window.history.back(); 40 // this.router.navigate(['/heros']); 41 42 } 43 44 save():void { 45 this.heroService.update(this.hero).then(this.goBack); 46 } 47 }
重点是详情页面的goBack()方法,我本来准备通过路由的navigate方法 来实现导航,并且router是通过构造函数注入,但是我在使用时this.router会为null,导致我无法通过这种方式实现页面跳转。
其实我想说的这个倒不是ng2的bug,可能有些地方没有设置成功,之所以说是bug,而是因为官方没有提供具体的详细信息。
有知晓的麻烦回复一下,我相信如果要使用页面跳转,肯定会用到。
更详细的内容可以参考官方的英雄列表。