Angular 2模板语法

前端之家收集整理的这篇文章主要介绍了Angular 2模板语法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

属性和事件绑定

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

input绑定

假设我们有一个组件来呈现的Todo,我们可以在我们的模板中使用这个组件,如下所示:

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

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

output绑定

现在,让我们添加一个事件使组件更有趣。

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

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

现在,让我们看看TodoCmp本身。

@Component@H_502_14@({
  selector: 'todo-cmp'@H_502_14@,input: ['model'@H_502_14@],output: ['complete'@H_502_14@]
})
class@H_502_14@ TodoCmp@H_502_14@ {@H_502_14@
  model;
  complete = new@H_502_14@ EventEmitter(); // TypeScript 支持初始化@H_502_14@

  onCompletedButton() {
    this@H_502_14@.complete.next(); // 触发事件@H_502_14@
  }
}

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

Angular使用Rx事件风格来处理事件的接收,EventEmitter即实现了observable,又实现了observer接口(规范),因此,我们可以用它来触发事件,并且Angular也可以用它来监听事件。

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

双向绑定

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

<input@H_502_14@ [ngModel@H_502_14@]="todo.text"@H_502_14@ (ngModel@H_502_14@)="todo.text=$event"@H_502_14@>@H_502_14@</input@H_502_14@>@H_502_14@

虽然这可以正常工作,但这太罗嗦。因为这是一个常见的模式,所以Angular提供语法糖简化这种写法。

<input@H_502_14@ [(ngModel@H_502_14@)]="todo.text"@H_502_14@>@H_502_14@</input@H_502_14@>@H_502_14@

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

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

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

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

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

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

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

插值

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

使用语法糖

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

绑定直接量

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

使用语法糖

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

移除括号

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

<some-component@H_502_14@ [prop@H_502_14@]="someExp"@H_502_14@ (event@H_502_14@)="someEvent()"@H_502_14@ [(twoWayProp@H_502_14@)]="someExp"@H_502_14@>@H_502_14@</show-title@H_502_14@>@H_502_14@

于上面相同

<@H_502_14@some-component@H_502_14@ bind-prop@H_502_14@=@H_502_14@"someExp"@H_502_14@ on@H_502_14@-event@H_502_14@=@H_502_14@"someEvent()"@H_502_14@ bindon-twoWayProp@H_502_14@=@H_502_14@"someExp"@H_502_14@><@H_502_14@/show-title@H_502_14@>@H_502_14@

局部变量

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

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

#player表示当前video-player组件自身,而没有#player的组件则可以通过player访问video-player组件

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

语法糖

<@H_502_14@video-player@H_502_14@ #player@H_502_14@><@H_502_14@/video-player@H_502_14@>@H_502_14@

相当于

<@H_502_14@video-player@H_502_14@ var@H_502_14@-player@H_502_14@><@H_502_14@/video-player@H_502_14@>@H_502_14@

模板和 *

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

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

<todo-cmp@H_502_14@ *ngFor@H_502_14@="#t of todos; #i=index"@H_502_14@ [model@H_502_14@]="t"@H_502_14@ [index@H_502_14@]="t"@H_502_14@>@H_502_14@</todo-cmp@H_502_14@>@H_502_14@

去除语法糖后变为

<template@H_502_14@ ngFor@H_502_14@ #item@H_502_14@="$implicit"@H_502_14@ [ngForOf@H_502_14@]="items"@H_502_14@ #i@H_502_14@="index"@H_502_14@>@H_502_14@
  <todo-cmp@H_502_14@ [model@H_502_14@]="t"@H_502_14@ [index@H_502_14@]="t"@H_502_14@>@H_502_14@</todo-cmp@H_502_14@>@H_502_14@
</template@H_502_14@>@H_502_14@

该ngFor指令在视图上会创建@H_502_14@ i@H_502_14@m@H_502_14@p@H_502_14@l@H_502_14@@H_502_14@i@H_502_14@c@H_502_14@i@H_502_14@t@H_502_14@@H_502_14@和@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@@H_502_14@ @H_502_14@index变量并绑定到模板上,在模板元素上声明的所有变量只能在元素内提供,这就是为什么以下是不正确

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

你需要重点理解的是,当你建立你自己的指令来处理视图时,你的 * Syntax 语法能扩展成什么。例如,如果你看ngfor,你会发现它有ngforof属性,但是没有of属性

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

web组件和原生元素

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

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

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

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

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

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

设计目标

我希望你能明白在Angular 2里模板语法是怎么运作的.现在,我想来讨论一下为什么它用这种方式运作?它这么设计的目的是什么?

我们的主要设计目标是使模板更加清晰,开发者在不知如果使用指令情况也能够理解和重构模板,以及指令是如何工作的。

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

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

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

在这里,我们可以看到,name可以被更新,因为我们使用[()]语法

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

<todo-cmp@H_502_14@ *ngFor@H_502_14@="#t of todos"@H_502_14@>@H_502_14@</todo-cmp@H_502_14@>@H_502_14@

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

@H_502_14@{{index@H_502_14@}}@H_502_14@ <div@H_502_14@ *ngFor@H_502_14@="#item of items; var index=index"@H_502_14@>@H_502_14@ @H_502_14@{{index@H_502_14@} </div@H_502_14@>@H_502_14@

这就是其中的一个Angular 2模板的实例分析。由于IDE可以分析模板,所以他们可以提供自动完成和重构。

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

转自:http://ng2.zai.io/edit/news/de8f9870e3c5513a

猜你在找的Angularjs相关文章