Angular 2 For JavaScript ES5 英雄编辑器教程-路由(6)

由于官网给出JavaScript例子不是很完整,此文主要简单的记录用JavaScript写Angular 2 的Hello World程序。

用javascript实现官网英雄指南教程

本文参照官网实例地址:TypeScript实现的英雄编辑器教程-路由

保持项目运行:在项目目录下执行npm start

1.本章结束后项目文件目录

angular-quickstart
|---app
|    |
|    |---app.component.css
|    |---app.component.js
|    |---app.module.js
|    |---app-routing.module.js
|    |---dashboard.component.css
|    |---dashboard.component.html
|    |---dashboard.component.js
|    |---hero.js
|    |---hero.service.js
|    |---hero-detail.component.css
|    |---hero-detail.component.html
|    |---hero-detail.component.js
|    |---heroes.component.css
|    |---heroes.component.html
|    |---heroes.component.js
|    |---main.js
|    |---mock-heroes.js
|
|---node_modules ...
|---package.json
|---systemjs.config.js
|---index.html
|---style.css

2.路由及导航-代码重构

AppComponent改写成应用程序的外壳,只处理导航,将其他功能转移到各自功能拆分到各自的组件内。

将APPComponent中的 功能移动至HeroesComponent。

可以将app.component.js复制改名为heroes.component.js

将AppComponent改名为HeroesComponent

将选择器selector从’my-app’改为’my-heroes’

修改后app/heroes.component.js片段

var ng_core = require('@angular/core');
var Hero = require('./hero').Hero;
var HeroService = require('./hero.service').HeroService;

var HeroesComponent = (function(){
    function HeroesComponent (){
    }
    HeroesComponent = ng_core.Component({
      selector: 'my-heroes',
      template:`
            <h2>My Heroes</h2>
            <ul class="heroes">
                <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
                    <span class="badge">{{hero.id}}</span> {{hero.name}}
                </li>
            </ul>
            <my-hero-detail [hero]="selectedHero"></my-hero-detail>
          `
    }).Class({
        constructor:[HeroService,function(heroService) {
            this.hero = new Hero(1,'Windstorm');
            this.heroService = heroService;
            //this.heroes = heroService.getHeroes();//HEROES;
            this.selectedHero = null; 
            this.onSelect = function(hero){
                this.selectedHero = hero;
            };
        }]
    });
    HeroesComponent.prototype.getHeroes = function(){
        return this.heroService.getHeroes();
    };
    HeroesComponent.prototype.ngOnInit = function(){
        this.heroes = this.getHeroes();
    };
    return HeroesComponent;
}());
exports.HeroesComponent = HeroesComponent;

重写app.component.js为入口

var ng_core = require('@angular/core');

var AppComponent = (function(){
    function AppComponent (){
    }
    AppComponent = ng_core.Component({
      selector: 'my-app',
      template:`
            <h1>{{title}}</h1>
            <my-heroes></my-heroes>
          `
    }).Class({
        constructor:function() {
            this.title = 'Tour of Heroes';
        }
    });
    return AppComponent;
}());
exports.AppComponent = AppComponent;

新建app/app.module.js

var ng_core = require('@angular/core');
var BrowserModule = require('@angular/platform-browser').BrowserModule;
var FormsModule = require('@angular/forms').FormsModule;

var AppComponent = require('./app.component').AppComponent;
var HeroDetailComponent = require('./hero-detail.component').HeroDetailComponent;
var HeroesComponent = require('./heroes.component').HeroesComponent;
var HeroService = require('./hero.service').HeroService;

var AppModule = (function(){
    function AppModule(){

    };
    AppModule = ng_core.NgModule({
      imports: [ BrowserModule,FormsModule],
      declarations: [ AppComponent,HeroDetailComponent,HeroesComponent],
      bootstrap: [ AppComponent ],
      providers:[HeroService]
    })
    .Class({
      constructor: function() {}
    });
    return AppModule;
}());
exports.AppModule = AppModule;

将HeroService提供到跟模块,从HeroesComponent移除,这样HeroService可以被多个视图进行共用。至此重构完成,代码重构后,与之前运行效果一致。

3.添加路由

在index.html中的head标签内添加标签,请将该标签加在head标签最开始,为相对路径提供根路径

在app/app.module.js中添加路由

var ng_core = require('@angular/core');
var BrowserModule = require('@angular/platform-browser').BrowserModule;
var FormsModule = require('@angular/forms').FormsModule;
var RouterModule = require('@angular/router').RouterModule;

var AppComponent = require('./app.component').AppComponent;
var HeroDetailComponent = require('./hero-detail.component').HeroDetailComponent;
var HeroesComponent = require('./heroes.component').HeroesComponent;
var HeroService = require('./hero.service').HeroService;

var AppModule = (function(){
    function AppModule(){

    };
    AppModule = ng_core.NgModule({
      imports: [ 
        BrowserModule,
        FormsModule,
        RouterModule.forRoot([
        {
            path:'heroes',
            component:HeroesComponent
        }
        ])
      ],
      declarations: [ AppComponent,HeroDetailComponent,HeroesComponent],
      bootstrap: [ AppComponent ],
      providers:[HeroService]
    })
    .Class({
      constructor: function() {}
    });
    return AppModule;
}());
exports.AppModule = AppModule;

修改app.component.js的template

template:`
            <h1>{{title}}</h1>
            <a routerLink="/heroes">Heroes</a>
            <router-outlet></router-outlet>
          `

点击a标签的Heroes,会将根据routerLink属性将该视图导航到/heroes,并且将该视图在router-outlet内显示

4.添加新组件-控制台

新建app/dashboard.component.js

var Component = require('@angular/core').Component;

var DashboardComponent = (function(){
    var DashboardComponent = function(){

    };
    DashboardComponent = Component({
        selector: 'my-dashboard',
        template: '<h3>My Dashboard</h3>'
    }).Class({
        constructor:function() {
        }
    });
    return DashboardComponent;
}());
exports.DashboardComponent = DashboardComponent;

在app/app.module.js中引入DashbordComponent,并且添加DashbordComponent组件到路由,并且如果未输入url,将默认重定向到DashboardComponent

app/app.module.js

var ng_core = require('@angular/core');
var BrowserModule = require('@angular/platform-browser').BrowserModule;
var FormsModule = require('@angular/forms').FormsModule;
var RouterModule = require('@angular/router').RouterModule;

var AppComponent = require('./app.component').AppComponent;
var HeroDetailComponent = require('./hero-detail.component').HeroDetailComponent;
var HeroesComponent = require('./heroes.component').HeroesComponent;
var HeroService = require('./hero.service').HeroService;
var DashboardComponent = require('./dashboard.component.js').DashboardComponent;

var AppModule = (function(){
    function AppModule(){

    };
    AppModule = ng_core.NgModule({
      imports: [ 
        BrowserModule,
        FormsModule,
        RouterModule.forRoot([
        {
            path:'heroes',
            component:HeroesComponent
        },{
          path: 'dashboard',
          component: DashboardComponent
        },{
          path: '',
          redirectTo: '/dashboard',
          pathMatch: 'full'
        }
        ])
      ],
      declarations: [ AppComponent,HeroDetailComponent,HeroesComponent,DashboardComponent],
      bootstrap: [ AppComponent ],
      providers:[HeroService]
    })
    .Class({
      constructor: function() {}
    });
    return AppModule;
}());
exports.AppModule = AppModule;

修改app/app.component.js模板,可以切换视图

template:`
           <h1>{{title}}</h1>
           <nav>
             <a routerLink="/dashboard">Dashboard</a>
             <a routerLink="/heroes">Heroes</a>
           </nav>
           <router-outlet></router-outlet>
          `

5.完善控制台

在控制台内,显示4个顶级英雄

将template提取到app/dashboard.component.html

<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <div *ngFor="let hero of heroes" class="col-1-4">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </div>
</div>

在app/dashbord.component.js中引用该文件,如果填写相对路径, 则此时需要systemjs提供CommonJs表中,便可以使用module.id来支持相对路径。

将HeroService注入到DashboardComponent,并选取第2、第3、第4、第5这几个英雄作为DashboardComponent的heroes

var Component = require('@angular/core').Component;
var HeroService = require('./hero.service').HeroService;

var DashboardComponent = (function(){
    var DashboardComponent = function(){

    };
    DashboardComponent = Component({
        moduleId: module.id,
        selector: 'my-dashboard',
        templateUrl: 'dashboard.component.html'
    }).Class({
        constructor:[HeroService,function(heroService) {
            this.heroService = heroService;
        }]
    });

    DashboardComponent.prototype.getHeroes = function(){
        return this.heroService.getHeroes();
    };
    DashboardComponent.prototype.ngOnInit = function(){
        this.heroes = this.getHeroes().slice(1, 5);
    };
    return DashboardComponent;
}());
exports.DashboardComponent = DashboardComponent;

6.路由到英雄详情页

修改app.module.js路由,添加如下内容

,{
  path: 'detail/:id',
    component: HeroDetailComponent
}

:id为占位符,可以通过占位符传递id

修改HeroDetailComponent,通过导航获取英雄id

向HeroDetailComponent中注入ActivatedRoute,Location,HeroService组件,并存储到HeroDetailComponent对象内。

引入需要的组件

var ActivatedRoute = require('@angular/router').ActivatedRoute;
var Location = require('@angular/common').Location;

var HeroService = require('./hero.service').HeroService;

HeroDetailComponent的构造函数

constructor:[HeroService,ActivatedRoute,Location,function(heroService,activatedRoute,location){
            this.heroService = heroService;
            this.route = activatedRoute;
            this.location = location;
        }]

实现 ngOnInit接口,回退方法

HeroDetailComponent.prototype.ngOnInit = function(){
        var params = this.route.params.value; 
        var id = parseInt(params['id']); //获取url传递过来的id
        var hero = this.heroService.getHero(id);
        this.hero = hero;
    }
    HeroDetailComponent.prototype.goBack = function(){
      this.location.back(); //回退到上一视图
    }

修改template,并将该模板存储到app/hero-detail.component.html

<div *ngIf="hero">
  <h2>{{hero.name}} details!</h2>
  <div>
    <label>id: </label>{{hero.id}}</div>
  <div>
    <label>name: </label>
    <input [(ngModel)]="hero.name" placeholder="name" />
  </div>
  <button (click)="goBack()">Back</button>
</div>

修改HeroDetailComponent组件元数据

HeroDetailComponent = ng_core.Component({
        moduleId: module.id,
        selector: 'my-hero-detail',
        templateUrl:'hero-detail.component.html',
        inputs:['hero'],
    }

在 HeroService中添加getHero方法

app/hero.service.js

    HeroService.prototype.getHero = function(id){
        for(var i in HEROES){
            var hero = HEROES[i];
            if(hero.id === id){
                return hero;
            }
        }
    }

修改app/dashboard.component.html文件

app/dashboard.component.html

<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of heroes"  [routerLink]="['/detail', hero.id]"  class="col-1-4">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>

至此,在dashboard视图下,点击以为英雄,将被导航至英雄详情页。

7.重构路由,新建路由模块

新建app/app-routing.module.js

var ng_core = require('@angular/core');
var RouterModule = require('@angular/router').RouterModule;


var HeroDetailComponent = require('./hero-detail.component').HeroDetailComponent;
var HeroesComponent = require('./heroes.component').HeroesComponent;
var DashboardComponent = require('./dashboard.component.js').DashboardComponent;

var AppRoutingModule = (function(){
    var routes = [
        {
          path: '',
          redirectTo: '/dashboard',
          pathMatch: 'full'
        },
        {
            path:'heroes',
            component:HeroesComponent
        },
        {
          path: 'dashboard',
          component: DashboardComponent
        },
        {
          path: 'detail/:id',
          component: HeroDetailComponent
        }
        ];
    var AppRoutingModule = function AppRoutingModule(){
    };
    AppRoutingModule = ng_core.NgModule({
      imports: [ RouterModule.forRoot(routes)],
      exports:[RouterModule]
    })
    .Class({
      constructor: function() {}
    });
    return AppRoutingModule;
}());
exports.AppRoutingModule = AppRoutingModule;

重写app/app.module.js

var ng_core = require('@angular/core');
var BrowserModule = require('@angular/platform-browser').BrowserModule;
var FormsModule = require('@angular/forms').FormsModule;

var AppComponent = require('./app.component').AppComponent;
var HeroDetailComponent = require('./hero-detail.component').HeroDetailComponent;
var HeroesComponent = require('./heroes.component').HeroesComponent;
var HeroService = require('./hero.service').HeroService;
var DashboardComponent = require('./dashboard.component').DashboardComponent;

var AppRoutingModule = require('./app-routing.module').AppRoutingModule;

var AppModule = (function(){
    function AppModule(){

    };
    AppModule = ng_core.NgModule({
      imports: [ 
        BrowserModule,
        FormsModule,
        AppRoutingModule
      ],
      declarations: [ AppComponent,HeroDetailComponent,HeroesComponent,DashboardComponent],
      bootstrap: [ AppComponent ],
      providers:[HeroService]
    })
    .Class({
      constructor: function() {}
    });
    return AppModule;
}());
exports.AppModule = AppModule;

8.重构HeroesComponent

重构HeroesComponent的template,并将其拆入app/uppercase.html、将style拆入到app/heroes.component.css

其中| uppercase为管道,可以将表示格式化显示为大写字母

<h2>My Heroes</h2>
<ul class="heroes">
    <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
    </li>
</ul>
<!--<my-hero-detail [hero]="selectedHero"></my-hero-detail>-->
<div *ngIf="selectedHero">
  <h2>
    {{selectedHero.name | uppercase}} is my hero //new 
  </h2>
  <button (click)="gotoDetail()">View Details</button>
</div>

重写app/heroes.component.js

var ng_core = require('@angular/core');

var Router = require('@angular/router').Router;

var Hero = require('./hero').Hero;
var HeroService = require('./hero.service').HeroService;

var HeroesComponent = (function(){
    function HeroesComponent (){
    }
    HeroesComponent = ng_core.Component({
        moduleId: module.id,
      selector: 'my-heroes',
      templateUrl:'heroes.component.html',
      styleUrls: ['heroes.component.css']
    }).Class({
        constructor:[HeroService,Router,function(heroService,router) {
            this.hero = new Hero(1,'Windstorm');
            this.heroService = heroService;
            this.router = router;
            this.selectedHero = null; 
            this.onSelect = function(hero){
                this.selectedHero = hero;
            };
        }]
    });
    HeroesComponent.prototype.getHeroes = function(){
        return this.heroService.getHeroes();
    };
    HeroesComponent.prototype.ngOnInit = function(){
        this.heroes = this.getHeroes();
    };
    HeroesComponent.prototype.gotoDetail = function(){
        this.router.navigate(['/detail', this.selectedHero.id]);
    }
    return HeroesComponent;
}());
exports.HeroesComponent = HeroesComponent;

9.美化

美化DashboardComponent,添加元数据styleUrls: [ ‘dashboard.component.css’ ]

新增app/dashboard.component.css

[class*='col-'] {
  float: left;
  padding-right: 20px;
  padding-bottom: 20px;
}
[class*='col-']:last-of-type {
  padding-right: 0;
}
a {
  text-decoration: none;
}
*, *:after, *:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
h3 {
  text-align: center; margin-bottom: 0;
}
h4 {
  position: relative;
}
.grid {
  margin: 0;
}
.col-1-4 {
  width: 25%;
}
.module {
  padding: 20px;
  text-align: center;
  color: #eee;
  max-height: 120px;
  min-width: 120px;
  background-color: #607D8B;
  border-radius: 2px;
}
.module:hover {
  background-color: #EEE;
  cursor: pointer;
  color: #607d8b;
}
.grid-pad {
  padding: 10px 0;
}
.grid-pad > [class*='col-']:last-of-type {
  padding-right: 20px;
}
@media (max-width: 600px) {
  .module {
    font-size: 10px;
    max-height: 75px; }
}
@media (max-width: 1024px) {
  .grid {
    margin: 0;
  }
  .module {
    min-width: 60px;
  }
}

美化HeroDetailComponent,添加元数据styleUrls: [ ‘hero-detail.component.css’ ],

新增app/hero-detail.component.css

label {
  display: inline-block;
  width: 3em;
  margin: .5em 0;
  color: #607D8B;
  font-weight: bold;
}
input {
  height: 2em;
  font-size: 1em;
  padding-left: .4em;
}
button {
  margin-top: 20px;
  font-family: Arial;
  background-color: #eee;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer; cursor: hand;
}
button:hover {
  background-color: #cfd8dc;
}
button:disabled {
  background-color: #eee;
  color: #ccc; 
  cursor: auto;
}

美化AppComponent,添加源数据styleUrls: [‘app.component.css’],

新增app/app.component.css

h1 {
  font-size: 1.2em;
  color: #999;
  margin-bottom: 0;
}
h2 {
  font-size: 2em;
  margin-top: 0;
  padding-top: 0;
}
nav a {
  padding: 5px 10px;
  text-decoration: none;
  margin-top: 10px;
  display: inline-block;
  background-color: #eee;
  border-radius: 4px;
}
nav a:visited, a:link {
  color: #607D8B;
}
nav a:hover {
  color: #039be5;
  background-color: #CFD8DC;
}
nav a.active {
  color: #039be5;
}

修改AppComponent的template,添加routerLinkActive属性,当连接激活时,添加样式

<a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>

修改style.css

/* Master Styles */
h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}
h2, h3 {
  color: #444;
  font-family: Arial, Helvetica, sans-serif;
  font-weight: lighter;
}
body {
  margin: 2em;
}
body, input[text], button {
  color: #888;
  font-family: Cambria, Georgia;
}
/* . . . */
/* everywhere else */
* {
  font-family: Arial, Helvetica, sans-serif;
}

10.本章附件

由于本章文件太多,不一一贴出,请参考附件

备注:javascript初学,不懂太多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值