Angular 2模板语法

来源:http://kittencup.com/javascript/2015/07/20/Angular%202%E6%A8%A1%E6%9D%BF%E8%AF%AD%E6%B3%95.htmljavascript

原文地址:http://victorsavkin.com/post/119943127151/angular-2-template-syntaxhtml

属性和事件绑定

属性和事件绑定在指令中是公开的API,数据从属性绑定流入指令,从事件中流出指令java

属性绑定

假设咱们有一个组件来呈现的Todo,咱们能够在咱们的模板中使用这个组件,以下所示:git

<todo-cmp [model]="myTodo"></todo-cmp> 

这告诉Angular,只要myTodo发生变化,当有一个新的todo时,Angular会经过模型来自动更新todo组件github

事件绑定

如今,让咱们添加一个事件使组件更有趣。web

<todo-cmp [model]="todo" (complete)="onCompletingTodo(todo)"></todo-cmp> 

当事件complete触发时会告诉Angular调用onCompletingTodo方法编程

如今,让咱们看看TodoCmp自己。ide

@Component({ selector: 'todo-cmp', properties: ['model'], events: ['complete'] }) class TodoCmp { model; complete = new EventEmitter(); // TypeScript 支持初始化 onCompletedButton() { this.complete.next(); // 触发事件 } } 

这个组件声明数据绑定的名字为model,事件名为complete工具

Angular使用Rx事件风格来处理事件的接收,EventEmitter即实现了observable,又实现了observer接口(规范),所以,咱们能够用它来触发事件,而且Angular也能够用它来监听事件。post

正如你所看到的,属性和事件绑定的核心语法很简单。在核心语法之上,Angular提供了一些语法糖,使表达经常使用的编程模式更加容易。重要的是要了解,这仅仅是语法糖,并且它不会改变语义。

双向绑定

双向数据绑定在某些状况下是很方便的,最值得注意的是处理输入,正如我刚才提到的,属性绑定用于数据从父传递给子,事件绑定用于从子到父的数据传递。所以,咱们可使用两种方法来实现双向绑定。

<input [ng-model]="todo.text" (ng-model)="todo.text=$event"></input>

虽然这能够正常工做,但这太罗嗦。由于这是一个常见的模式,因此Angular提供语法糖简化这种写法。

<input [(ng-model)]="todo.text"></input> 

要完成这个例子,让咱们来实现Angular 2的ng-model

@Directive({
  selector: '[ng-model]',
  properties: ['ngModel'],
  events: ['ngModelChanged: ngModel'],
  host: {
    "[value]": 'ngModel',
    "(input)": "ngModelChanged.next($event.target.value)"
  }
})
class NgModelDirective {
  ngModel:any; // stored value
  ngModelChanged:EventEmitter; // an event emitter
}

这是一种比较幼稚的ngModel实现,但它说明了如何实现双向数据绑定行为:输入将在text发生更改时更新,并在输入更改时更新text字段。

请注意,于Angular 1相反,你只要看看模板就能够知道哪些绑定是“双向”,哪些是“单向”。

此外,由于只有一个方向,属性绑定,被Angular自动执行,双向的行为更可预测的。

它不会破坏任何Angular 2的语法:这只是一些语法糖,没有别的。

我想提一提,你不用去实现NgModel。Angular 2配备了一个表单处理模块,其包括NgModel的实现。

插值

<div>Hello {{name}}</div> 

使用语法糖

<div [textContent]="interpolate(['Hello'], [name])"></div> 

绑定直接量

<show-title title="Some Title"></show-title> 

使用语法糖

<show-title [title]=" 'Some Title' "></show-title> 

移除括号

你可使用bind-,in-和bindon-在你的模板中代替全部的括号,虽然这几乎不能称为“语法糖”

<some-component [prop]="someExp" (event)="someEvent()" [(two-way-prop)]="someExp"></show-title> 

于上面相同

<some-component bind-prop="someExp" on-event="someEvent()" bindon-two-way-prop="someExp"></show-title> 

局部变量

有两个组件互相交互,这种状况并很多见,Angular 2在模板中支持定义的局部变量。

<video-player #player></video-player> <button (click)="player.pause()">Pause</button> 

#player表示当前video-player组件自身,而没有#player的组件则能够经过player访问video-player组件

<input #i> {{i.value}} 

语法糖

<video-player #player></video-player> 

至关于

<video-player var-player></video-player> 

模板和 *

Angular以特殊的方式对待template元素。它们用来建立视图,你能够动态操做DOM块,*语法是一种捷径,它可使你不用写出所有的<template>元素,让我告诉你它是如何工做。

假设咱们呈现Todo列表组件。

<todo-cmp *ng-for="#t of todos; #i=index" [model]="t" [index]="t"></todo-cmp> 

去除语法糖后变为

<todo-cmp template="ng-for #item of items; #i=index" [model]="t" [index]="i"></todo-cmp> 

再一次去除语法糖后变为

<template ng-for #item="$implicit" [ng-for-of]="items" #i="index"> <todo-cmp [model]="t" [index]="t"></todo-cmp> </template> 

该ngFor指令在视图上会建立$implicit和$index变量并绑定到模板上,在模板元素上声明的全部变量只能在元素内提供,这就是为何如下是不正确

<todo-cmp *ng-for="#t of todos"></todo-cmp> {{t}} <!-- t cannot be referenced here --> 

你须要重点理解的是,当你创建你本身的指令来处理视图时,你的 * syntax 语法能扩展成什么。例如,若是你看ngfor,你会发现它有ngforof属性,可是没有of属性。

为何不对ng-for自定义语法,象angular 1同样呢?这有几个很好的理由。有自定义语法意味着你必须知道这个微语言如何操做。这也意味着在工具(例如,IDE和LInter)中不能理解你的模板并且并不能提供自动完成和重构。

web组件和原生元素

在这篇博客我谈到了一切的内容 - 局部变量,属性和事件绑定 - 对于web组件和标准的html元素来说使用方式是彻底相同

我能够用Web组件更换TodoCmp,仍然使用相同方式与它进行交互。

<todo-cmp [model]="todo" (completed)="onCompletingTodo(todo)"></todo-cmp> 

我能够用Web组件更换视频播放器,仍然使用相同方式与它进行交互。

<video-player #player></video-player> <button (click)="player.pause()">Pause</button> 

这将变得极为重要,由于更多的组件库可用。当运行在非Angular组件上也很重要(这是Angular 2目标之一),否者你不得不把每个原生组件包装成一个Angular 2组件,那真的很糟糕。Angular 2你能够直接使用任何本地组件,使用相同的语法,只有当你例如想使用依赖注入时,可将它包装为Angular组件

设计目标

我但愿你能明白在Angular 2里模板语法是怎么运做的.如今,我想来讨论一下为何它用这种方式运做?它这么设计的目的是什么?

咱们的主要设计目标是使模板更加清晰,开发者在不知若是使用指令状况也可以理解和重构模板,以及指令是如何工做的。

<component [property1]="name" property2="name"></component> 

无论组件元素是什么,property1是指向一个name变量的属性 property2属性只表示一个name字符串,你也须要知道,组件的property2属性没法更新,property1属性绑定更新是从父到子。

<component [(property1)]="name"></component> 

在这里,咱们能够看到,name能够被更新,由于咱们使用[()]语法

一样,你能够告诉在模板中定义了哪些变量,来看这里的*nf-for

<todo-cmp *ng-for="#t of todos"></todo-cmp> 

其次,咱们但愿有丰富的开发工具,在下面的列子中,工具能够静态地推断出第一个index是组件上的字段,而第2个index是ng-for输出的局部变量

{{index}}
<div *ng-for="#item of items; var index=index"> {{index} </div> 

这就是其中的一个Angular 2模板的实例分析。因为IDE能够分析模板,因此他们能够提供自动完成和重构。

最后,咱们要本地组件和web组件无缝集成。这意味着Angular 不能有特殊的特定事件(例如,ng-click),而必须提供通用机制,更新任何属性或监放任何事件。

相关文章
相关标签/搜索