(四)Angular4 英雄征途HeroConquest-主从结构

(四)Angular4 英雄征途HeroConquest-主从结构


主从结构

在一个组件的中同时,包含一个主结构模块,包含另外几个从模块,从模块依赖于主模块。

app.component.ts文件

导入angular4核心模块:

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

定义模板:

@Component({
  selector: 'app-root',
  template: `<h1>{{title}}</h1>
<!--上一节代码begin-->
  <br>
 <h2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------{{from}}</h2>
  <ul>
  <li>
  <div><label>ID:</label>{{hero.id}}&nbsp;<label> name:</label>{{hero.name}}</div>
  </li>
  </ul>
  <div>
  <label>name: </label>
  <input [(ngModel)]="hero.name" >
  <label>ID: </label>
  <input  [ngModel]="hero.id" (ngModelChange)="hero.id=$event">
</div>
<!--上一节代码end-->
<!--本节代码begin-->
<!--主结构如下:-->
<div>
<ul class="heroes">
<li *ngFor="let onehero of Heros" (click)="onSelect(onehero)" [class.selected]="onehero===selectedHero">
<span class="badge">ID:{{onehero.id}}</span>&nbsp;{{onehero.name}}
</li>
</ul>
</div >
<!--
首先利用*ngFor="expression"展示Hero数组中的每一个;其次但点击<li></li>控件-->
<!--的时候出发onSelect()这个函数,将并将出发的<li></li>中的onehero值作为函数实参-->
<!--传入;而后判断通过onSelect函数的处理--将onehero赋值给selectedHero;因此,在-->
<!--样式呈现的表达式中,如果被点击的onehero==selectedHer那么将样式selected呈现出来。-->

<!--从结构如下:-->
<div *ngIf="selectedHero">
<h2>{{selectedHero.name}} details!</h2>
<label>id: </label>{{selectedHero.id}}
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
</div>
</div>
<!--显然,当在主结构中,selectedHero被赋值,那么他就不为空,所以*ngIf="expression"中的将会expression的值将为真,所以这个<div></div>中的数据将会呈现出来-->
<!--本节代码end-->
  `
  ,
  styleUrls: ['./app.component.css']
})

类和属性的定义

export class AppComponent {
  title = 'My conquest is the sea of stars.';
  from = 'Reinhard von Lohengramm';
  hero: HeroProperty = {
    id: 9527,
    name: 'Lee',
  };

  Heros = HeroArray;
  selectedHero: HeroProperty;

// 如果没有selectedHero的初始化并且没有*ngIf,会出现加载页面时,所有模型数据呈现失败。
//原因是刚开始加载页面selectedHero的Dom没有值,一加载页面,浏览器加载不出来,
//所以干脆就都不呈现,一旦触发才全部显现(这个现象专业数据叫啥,哪位前辈若懂,
//还请留言指点,我猜测和ng4脏值检测机制有关)
//解决方案一: selectedHero初始化,不然模板里的{{}}内的表达式都不会显现,初始化如下:
// selectedHero: HeroProperty = {
//   id: 7,
// };
// 解决方案二:利用*ngIf ,在被选择之前移除从结构的跟selectedHero的模型数据呈//现相关的标签,或者所有从结构,ngIf的移除,是连Dom一块移除的,而不是单纯地隐//藏,再点击<li></li>选择之前,从结构的数据是不会出现在Dom里的,从而避免了解//决selectedHero空数据(undefined,我们会看到浏览器控制台中出现下列错//误:EXCEPTION: TypeError: Cannot read property 'name' of undefined in //[null])加载造成的模型数据整体读取失败

  // Tslint 定义class时出现后缀报错,重新剪切赋值源码
  onSelect(each: HeroProperty): void {
    this.selectedHero = each;
  }
}
const HeroArray: HeroProperty[] = [
  { id: 1, name: 'Asimov' },
  { id: 2, name: 'IronMan' },
  { id: 3, name: 'Gen' },
  { id: 4, name: 'AnglovLee' }
];
export class HeroProperty {
  id: number;
  name: string;
}

总结如下:当应用加载时,我们会看到一个英雄列表,但还没有任何英雄被选中。selectedHero属性是undefined。 因此,虽然我们要在模板中显示的是selectedHero.name,但在选中了一个英雄之前,我们必须让这些英雄详情留在DOM之外。我们可以把模板中的英雄详情内容区放在一个div标签中然后,添加一个ngIf内置指令,把ngIf的值设置为组件的selectedHero属性。当没有选中英雄时,ngIf指令会从 DOM 中移除表示英雄详情的这段 HTML 。 没有了表示英雄详情的元素,也就不用担心绑定问题。当用户选取了一个英雄,selectedHero变成了“已定义的”值,于是ngIf把英雄详情加回 DOM 中,并计算它所嵌套的各种绑定。


完整app.component.ts代码

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

@Component({
  selector: 'app-root',
  template: `<h1>{{title}}</h1>
<!--上一节代码begin-->
  <br>
  <h2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------{{from}}</h2>
  <ul>
  <li>
  <div><label>ID:</label>{{hero.id}}&nbsp;<label> name:</label>{{hero.name}}</div>
  </li>
  </ul>
  <div>
  <label>name: </label>
  <input [(ngModel)]="hero.name" >
  <label>ID: </label>
  <input  [ngModel]="hero.id" (ngModelChange)="hero.id=$event">
</div>
<div>
<ul class="heroes">
<li *ngFor="let onehero of Heros" (click)="onSelect(onehero)" [class.selected]="onehero===selectedHero">
<span class="badge">ID:{{onehero.id}}</span>&nbsp;{{onehero.name}}
</li>
</ul>

</div >
<!--上一节代码end-->
<!--本节代码begin-->
<div *ngIf="selectedHero">
<h2>{{selectedHero.name}} details!</h2>
<label>id: </label>{{selectedHero.id}}
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
</div>
</div>
<!--本节代码end-->
  `
  ,
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'My conquest is the sea of stars.';
  from = 'Reinhard von Lohengramm';
  hero: HeroProperty = {
    id: 9527,
    name: 'Lee',
  };

  Heros = HeroArray;
  selectedHero: HeroProperty;

  onSelect(each: HeroProperty): void {
    this.selectedHero = each;
  }
}
const HeroArray: HeroProperty[] = [
  { id: 1, name: 'Asimov' },
  { id: 2, name: 'IronMan' },
  { id: 3, name: 'Gen' },
  { id: 4, name: 'AnglovLee' }
];
export class HeroProperty {
  id: number;
  name: string;
}

app.component.css文件

.selected {
  background-color: #CFD8DC !important;
  color: white;
}
.heroes {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 15em;
}
.heroes li {
  cursor: pointer;
  position: relative;
  left: 0;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}
.heroes li.selected:hover {
  background-color: #BBD8DC !important;
  color: white;
}
.heroes li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}
.heroes .text {
  position: relative;
  top: -3px;
}
.heroes .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}

app.module.ts文件

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

猜你喜欢

转载自blog.csdn.net/changerjjlee/article/details/76715155