angular2 (v2.0)

来源:互联网 发布:期货盈利交易系统优化 编辑:程序博客网 时间:2024/05/14 15:07

在实际开发中可能需要不止一个模块,我们可以引入angular提供的模块,当然也可以自定义模块。

.无论是angular提供的还是自定义的模块都要在头部用imports导入

//例import { AppComponent }  from './app.component';

.在根模块会有一个@NgModule的装饰器修饰的类,结构大概如下:

@NgModule({    imports:      [        BrowserModule,        MainModule,        MainRoutingModule    ],    declarations: [        AppComponent,    ],    bootstrap:    [        AppComponent,    ],    providers: [        ItemService,    ],})
  • imports — 这个数组里面放的都是所谓的模块(module)。
  • declarations — 只有可以声明的 — 组件、指令和管道 — 属于declarations数组。 不要将其他类型的类添加到declarations中,例如NgModule类, 服务类,模型类。
  • bootstrap — 根组件,Angular 创建它并插入index.html宿主页面。
  • providers — 注册一个service的提供商,来告诉注入器如何创建服务的。

providers数组可以放在根模块下,也可以放在需要这个服务的组件(component)的@Component装饰器中;区别在于,定义在根模块一次可以在其他所有的组件中实例化,而放在某个组件中只可以在这个组件中实例化,在其他组件中实例化还要重新创建providers.

.自定义模块
创建名为module的文件即可demo.module.ts,自定义模块与根模块代码架构基本一样,需要注意的是自定义模块的类要暴露出去
还要再增加一个数组exports:

/* *demo.module.ts */@NgModule({    exports: [        DemoComponent,    ],})

然后在根模块用import导入自定义模块,并在根模块的imports数组中添加自定义模块

.服务(service)

1.服务命名一般为demo.service.ts.里面可以定义一些方法对数据进行操作。

@Injectable()export class DemoService {     getDemoes(): Promise<Demo[]> {         return Promise.resolve(DEMOES);     }}

有关Promise可以看一下ES6的Promise的部分。

2.刚才提到创建服务之后要在根模块用providers数组进行注册(当然也要在头部用import导入),然后在需要服务的组件中实例化,代码如下:

export class DemoComponent implements OnInit{    items : Item[];    //实例化service    constructor(        private itemService: ItemService,    ){}    ngOnInit(): void {        //调用service的方法        this.itemService.getItems().then(items => this.items = items);    }}

.路由(route)

带路由参数的跳转只能用事件绑定的方法,因为链接是不支持routerLink绑定的,会报错。用这种方式跳转:

onSelect(item: Item): void {    this.router.navigate(['/template', item.id]);}

.自定义属性型指令(directive)

//例:highlight.directive.tsimport { Directive, ElementRef, Renderer } from '@angular/core';@Directive({ selector: '[highlight]' })/** Highlight the attached element in gold */export class HighlightDirective {  constructor(renderer: Renderer, el: ElementRef) {    renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'gold');    console.log(      `* AppRoot highlight called for ${el.nativeElement.tagName}`);  }}

使用:

template: '<h1 highlight>{{title}}</h1>'

并且添加到Module中的declarations数组中。

如果指令名相同,可以使用as为指令指定别名:

//例import {  HighlightDirective as ContactHighlightDirective} from './contact/highlight.directive';

.自定义管道(pipe)

//例:awesome.pipe.tsimport { Pipe, PipeTransform } from '@angular/core';@Pipe({ name: 'awesome' })/** Precede the input string with the word "Awesome " */export class AwesomePipe implements PipeTransform {  transform(phrase: string) {    return phrase ? 'Awesome ' + phrase : '';  }}

使用与指令类似。

.响应用户引发事件—鼠标事件
使用@HostListener装饰器引用属性型指令的宿主元素。
示例代码:

装饰器后面有定要有();如@Input()、@HostListener()…,有得()里面可以有东西。

/**highlight.directive.ts*/import { Directive, ElementRef, HostListener, Input, Renderer } from '@angular/core';@Directive({  selector: '[myHighlight]'})export class HighlightDirective {  constructor(private el: ElementRef, private renderer: Renderer) { }  @HostListener('mouseenter') onMouseEnter() {    this.highlight('yellow');  }  @HostListener('mouseleave') onMouseLeave() {    this.highlight(null);  }  private highlight(color: string) {    this.renderer.setElementStyle(this.el.nativeElement, 'backgroundColor', color);  }}

也可以绑定一个可定制属性,当然也可以绑定多个,在highlight.directive.ts中这样写:

import { Directive, ElementRef, HostListener, Input, Renderer } from '@angular/core';@Directive({  selector: '[myHighlight]'})export class HighlightDirective {  private _defaultColor = 'red';  constructor(private el: ElementRef, private renderer: Renderer) { }  @Input() set defaultColor(colorName: string){    this._defaultColor = colorName || this._defaultColor;  }  @Input('myHighlight') highlightColor: string;  @HostListener('mouseenter') onMouseEnter() {    this.highlight(this.highlightColor || this._defaultColor);  }  @HostListener('mouseleave') onMouseLeave() {    this.highlight(null);  }  private highlight(color: string) {    this.renderer.setElementStyle(this.el.nativeElement, 'backgroundColor', color);  }}

在html中这样写:

<p [myHighlight]="color" [defaultColor]="'violet'">  Highlight me too!</p>

.模板语法
HTML attribute 与 DOM property 的对比
要想理解 Angular 绑定如何工作,重点是搞清 HTML attribute 和 DOM property 之间的区别。

attribute 是由 HTML 定义的。property 是由 DOM (Document Object Model) 定义的。

少量 HTML attribute 和 property 之间有着 1:1 的映射,如id。
有些 HTML attribute 没有对应的 property,如colspan。
有些 DOM property 没有对应的 attribute,如textContent。
大量 HTML attribute看起来映射到了property…… 但却不像我们想的那样!
最后一类尤其让人困惑…… 除非我们能理解这个普遍原则:

attribute 初始化 DOM property,然后它们的任务就完成了。property 的值可以改变;attribute 的值不能改变。

例如,当浏览器渲染时,它将创建相应 DOM 节点, 其value property 被初始化为 “Bob”。

当用户在输入框中输入 “Sally” 时,DOM 元素的value property 变成了 “Sally”。 但是这个 HTML value attribute 保持不变。如果我们读取 input 元素的 attribute,就会发现确实没变: input.getAttribute(‘value’) // 返回 “Bob”。
就算名字相同,HTML attribute 和 DOM property 也不是同一样东西。

由上面angular2的语法可知,当我们要设置属性(attribute)时,就不能用正常的方法绑定

我们需要 attribute 绑定来创建和绑定到这样的 attribute。

attribute 绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而是由attr前缀,一个点 (.) 和 attribute 的名字组成。 可以通过值为字符串的表达式来设置 attribute 的值。

这里把[attr.colspan]绑定到一个计算值:

<table border=1>  <!--  expression calculates colspan=2 -->  <tr><td [attr.colspan]="1 + 1">One-Two</td></tr>  <!-- ERROR: There is no `colspan` property to set!    <tr><td colspan="{{1 + 1}}">Three-Four</td></tr>  -->  <tr><td>Five</td><td>Six</td></tr></table>

绑定CSS类的时候,CSS 类绑定绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而是由class前缀,一个点 (.)和 CSS 类的名字组成, 其中后两部分是可选的。形如:[class.class-name]。

样式绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而由style前缀,一个点 (.)和 CSS 样式的属性名组成。 形如:[style.style-property]。

<button [style.color] = "isSpecial ? 'red': 'green'">Red</button><button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>/******************************************************/<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button><button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>

NgClass

setClasses() {  let classes =  {    saveable: this.canSave,      // true    modified: !this.isUnchanged, // false    special: this.isSpecial,     // true  };  return classes;}/**html*/<div [ngClass]="setClasses()">This div is saveable and special</div>

NgStyle

setStyles() {  let styles = {    // CSS property names    'font-style':  this.canSave      ? 'italic' : 'normal',  // italic    'font-weight': !this.isUnchanged ? 'bold'   : 'normal',  // normal    'font-size':   this.isSpecial    ? '24px'   : '8px',     // 24px  };  return styles;}/**html*/<div [ngStyle]="setStyles()">  This div is italic, normal weight, and extra large (24px).</div>

NgSwitch

<span [ngSwitch]="toeChoice">  <span *ngSwitchCase="'Eenie'">Eenie</span>  <span *ngSwitchCase="'Meanie'">Meanie</span>  <span *ngSwitchCase="'Miney'">Miney</span>  <span *ngSwitchCase="'Moe'">Moe</span>  <span *ngSwitchDefault>other</span></span>

带索引的 NgFor

<div *ngFor="let hero of heroes; let i=index">{{i + 1}} - {{hero.fullName}}</div>

NgForTrackBy(追踪函数)
我们知道这一点,是因为每个元素的属性没有变化。 但在 Angular 看来,它只是一个由新的对象引用构成的新列表, 它没有选择,只能清理旧列表、舍弃那些 DOM 元素,并且用新的 DOM 元素来重建一个新列表。
所以我们给他一个追踪函数,就像这样:

trackByHeroes(index: number, hero: Hero) { return hero.id; }

然后,把NgForTrackBy指令设置为那个追踪函数。

<div *ngFor="let hero of heroes; trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>

追踪函数不会阻止所有 DOM 更改。 如果同一个英雄的属性变化了,Angular 就可能不得不更新DOM元素。 但是如果这个属性没有变化 —— 而且大多数时候它们不会变化 —— Angular 就能留下这些 DOM 元素。列表界面就会更加平滑,提供更好的响应。

.模板引用变量
1.引用模板引用变量

可以在同一元素、兄弟元素或任何子元素中引用模板引用变量。

这里是关于创建和使用模板引用变量的另外两个例子:

<!-- phone refers to the input element; pass its `value` to an event handler --><input #phone placeholder="phone number"><button (click)="callPhone(phone.value)">Call</button><!-- fax refers to the input element; pass its `value` to an event handler --><input ref-fax placeholder="fax number"><button (click)="callFax(fax.value)">Fax</button>

“phone” 的井号 (#) 前缀表示定义了一个phone变量。
有些人不喜欢使用#字符,而是使用它的规范形式:ref-前缀。 例如,既能用#phone,也能用ref-phone来定义phone变量。

2.NgForm 和模板引用变量
表单,使用模板引用变量的典范:

<form (ngSubmit)="onSubmit(theForm)" #theForm="ngForm">  <div class="form-group">    <label for="name">Name</label>    <input class="form-control" name="name" required [(ngModel)]="currentHero.firstName">  </div>  <button type="submit" [disabled]="!theForm.form.valid">Submit</button></form>

theForm变量的值是什么?
如果 Angular 没有接管它,那它可能是个HTMLFormElement。 实际上它是个ngForm,对 Angular 内置指令NgForm的引用。 它包装了原生的HTMLFormElement并赋予它更多超能力,比如跟踪用户输入的有效性。
这解释了该如何通过检查theForm.form.valid来禁用提交按钮,以及如何把一个信息量略大的对象传给父组件的onSubmit方法。

0 0