Angular4-模板语法
Angular4 - 模板语法
1. 模板语法的介绍
HTML 是 Angular 模板的语⾔。⼏乎所有的HTML语法都是有效的模板语法。但值得注意的例外是<script>元素,它被禁⽤了,以阻⽌脚本注⼊攻击的风险。(实际上,<script>只是被忽略了。)
有些合法的 HTML 被⽤在模板中是没有意义的。<html>、<body>和<base>元素这个舞台上中并没有扮演有⽤的⾓⾊。剩下的所有元素基本上就都⼀样⽤了。这些元素存在于index.html中。
可以通过组件和指令来扩展模板中的 HTML 词汇。它们看上去就是新元素和属性。
那么模板语法是什么呢?
对于⼀个简单的html代码,我们可以在页⾯内配置css属性,绑定事件,设计element元素的位置达到我们想要的结果。以此类推到Angular模板中来说。模板语法规定了以下内容(⾃我总结):
*规定了html词汇(script被忽略,html,body,base没有意义,扩展指令和组件)
*扩展插值表达式和扩展模板表达式
*扩展了绑定语法(规定了属性绑定,事件绑定的语法以及双向绑定内容)
*模板引⽤变量 (请查看组件章节)
*Angular内置指令(本章不会讲解,后续指令⽂章会有说明)
*Angular⾃定义指令(本章不会讲解,后续指令⽂章会有说明)
总⽽⾔之,模板语法是规定了我们操作template内容以达到我们想要的结果
2. 插值表达式和模板表达式
(1) 插值表达式
{{}}称为插值表达式,可以将当前组件控制器中的公有变量直接取值然后显⽰其值。
I am {{employee.name}}
//angularponent.ts
export class AngularComponent implements OnInit {
public employee: Employee = {
name: 'rodchen',
company: 'aug'
}
constructor() {
}
ngOnInit(): void {
}
}
插值表达式还可以将计算过的字符串插⼊到HTML元素标签内或对标签的属性进⾏赋值
<h3>
{{title}}
<img src="{{heroImageUrl}}" >
</h3>
(2) 模板表达式
模板表达式产⽣⼀个值。 Angular执⾏这个表达式,并把它赋值给绑定⽬标的属性,这个绑定⽬标可能是 HTML 元素、组件或指令
。插值表达式其实就是模板表达式,只是上⾯我们只是将控制器中的变量值直接赋给元素。如果{{}}中发⽣了计算,那么我们可以称作模板表达式。模板表达式可以是数字计算
<p>The sum of 1 + 1 is {{1 + 1}}</p>
也可以是调⽤宿主组件的⽅法
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}</p>
模板表达式看起来javascript表达式,但是是有⼀些规定:
JavaScript中那些具有或可能引发副作⽤的表达式是被禁⽌的,包括:
赋值 (=, +=, -=, ...)
new运算符
htmlbutton属性使⽤;或,的链式表达式
⾃增或⾃减操作符 (++和--)
和 JavaScript语法的其它显著不同包括:
不⽀持位运算|和&
具有新的模板表达式运算符,⽐如|、?.和!。
(3) 模板表达式操作符
a) 管道操作符 ( | )
在绑定之前,表达式的结果可能需要⼀些转换。例如,可能希望把数字显⽰成⾦额、强制⽂本变成⼤写,或者过滤列表以及进⾏排序。
I am {{employee.name | uppercase}} //I am RODCHEN
具体⽤法可以参照 ,后⾯也会有专门的⽂章去学习。
b) 安全导航操作符 ( ?. ) 和空属性路径
Angular 的安全导航操作符 (?.) 是⼀种流畅⽽便利的⽅式,⽤来保护出现在属性路径中 null 和 undefined 值。例如a)中的例⼦,如果employee是null,页⾯会发⽣是什么呢?
"I am"依然会渲染,但是会报错。
TypeError: Cannot read property 'name' of null in [null].
这时我们就可以使⽤安全导航操作符来规避这个错误。
I am {{employee?.name | uppercase}}
c) ⾮空断⾔操作符(!)
如果类型检查器在运⾏期间⽆法确定⼀个变量是null或undefined,那么它也会抛出⼀个错误。我们⾃⼰可能知道它不会为空,但类型检查器不知道。所以我们要告诉类型检查器,它不会为空,这时就要⽤到⾮空断⾔操作符。
Angular 模板中的**⾮空断⾔操作符(!)也是同样的⽤途。
例如,在⽤*ngIf来检查过hero是已定义的之后,就可以断⾔hero属性⼀定是已定义的。
src/app/appponent.html
content_copy
<!--No hero, no text -->
<div *ngIf="hero">
The hero's name is {{hero!.name}}
</div>
在 Angular 编译器把你的模板转换成 TypeScript 代码时,这个操作符会防⽌ TypeScript 报告 "hero.na
me可能为null或undefined"的错误。
与安全导航操作符不同的是,⾮空断⾔操作符不会防⽌出现null或undefined。 它只是告诉 TypeScript 的类型检查器对特定的属性表达式,不做 "严格空值检测"。
如果我们打开了严格控制检测,那就要⽤到这个模板操作符,⽽其它情况下则是可选的。
(4) 插值表达式的实现
<h3>
{{title}}
<img src="{{heroImageUrl}}" >
</h3>
表⾯上看,我们在元素标签之间插⼊了结果和对标签的属性进⾏了赋值。 这样思考起来很⽅便,并且这个误解很少给我们带来⿇烦。 但严格来讲,这是不对的。插值表达式是⼀个特殊的语法,Angular 把它转换成了属性绑定。属性绑定后⾯会说到。
3. 绑定语法
数据绑定是⼀种机制,⽤来协调⽤户所见和应⽤数据。虽然我们能往 HTML 推送值或者从 HTML 拉取值,但如果把这些琐事交给数据绑定框架处理,应⽤会更容易编写、阅读和维护。只要简单地在绑定源和⽬标 HTML 元素之间声明绑定,框架就会完成这项⼯作。
(1) 绑定类型
a)单向从数据源到视图⽬标
插值表达式 {{expression}}
DOM Property绑定 [target]="expression"
HTML Attribute绑定 [attr.target]="expression"
CSS 类绑定 [class.class-name]="expression"
样式绑定 [target]="expression"
b) 单向从视图⽬标到数据源
事件绑定 (target)="statement"
c) 双向绑定
[(target)]="expression"
(2) HTML attribute 与 DOM property 的对⽐
介绍绑定之前,还是先看⼀个重要的问题: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 的值不能改变。
举个例⼦:
<input type="text" value="name" (input)="onPut($event)">
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-angular',
templateUrl: './angularponent.html',
styleUrls: ['./angularponent.css']
})
export class AngularComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
onPut(event) {
console.log('DOM 属性: ' + event.target.value);
console.log('HTML 属性: ' + Attribute('value'));
}
}
如下图所⽰,我们可以看到随着我们的输⼊,DOM属性会变化,但是html属性不会发⽣变化。
在看⼀个关于disabled的例⼦:
<button disabled>点击</button>
当前这个button是不可以点击的,因为出现了disabled属性。
<button disabled="false">点击</button>
当我将disables(html属性)设置为false,这个button还是不可以的。添加或删除disabled attribute会禁⽤或启⽤这个按钮。但 attribute 的值⽆关紧要,这就是我们为什么没法通过 <button disabled="false">仍被禁⽤</button>这种写法来启⽤按钮。
但是我们可以通过DOM属性来启⽤button。
<button [disabled]="false">点击</button>
模板绑定是通过 property 和事件来⼯作的,⽽不是 attribute。在 Angular 的世界中,attribute 唯⼀的作⽤是⽤来初始化元素和指令的状态。 当进⾏数据绑定时,只是在与元素和指令的 property 和事件打交道,⽽ attribute 就完全靠边站了。
4 绑定⽬标
(1) 单向从数据源到视图⽬标
a) 插值表达式
{{employee.name}}
b) 属性绑定(DOM属性绑定)
//[target]="expression"
<input type="text" [value]="name" />
有些⼈喜欢⽤bind-前缀的可选形式,并称之为规范形式:
<input type="text" bind-value="name" />
属性绑定还是插值表达式?
<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p>
当要渲染的数据类型是字符串时,没有技术上的理由证明哪种形式更好。 我们倾向于可读性,所以倾向于插值表达式。 建议建⽴代码风格规则,选择⼀种形式, 这样,既遵循了规则,⼜能让⼿头的任务做起来更⾃然。但数据类型不是字符串时,就必须使⽤属性绑定了。
c) attribute绑定
[attr.target]="expression"
可以通过attribute 绑定来直接设置 attribute 的值。
为什么 Angular 还提供了 attribute 绑定呢?
因为当元素没有属性可绑的时候,就必须使⽤ attribute 绑定。
<tr><td colspan="{{ 1 + 1 }}">One-Two</td></tr>
正如提⽰中所说,<td>元素没有colspan属性。 但是插值表达式和属性绑定只能设置属性,不能设置 attribute。我们需要 attribute 绑定来创建和绑定到这样的 attribute。
attribute 绑定的语法与属性绑定类似。 但⽅括号中的部分不是元素的属性名,⽽是由attr前缀,⼀个点 (.) 和 attribute 的名字组成。 可以通过值为字符串的表达式来设置 attribute 的值。
这⾥把[lspan]绑定到⼀个计算值:
<tr><td [lspan]="1 + 1">One-Two</td></tr>
d) CSS 类绑定
借助 CSS 类绑定,可以从元素的class attribute 上添加和移除 CSS 类名。CSS 类绑定绑定的语法与属性绑定类似。但⽅括号中的部分不是元素的属性名,⽽是由class前缀,⼀个点 (.)和 CSS 类的名字组成,其中后两部分是可选的。形如:[class.class-name]。
举个例⼦:
.color-class {
color: red;
}
<div>
<div class="color-class">
<p>Test the css class bind</p>
</div>
</div>
此时页⾯上的⽂字为红颜⾊。
然后我们使⽤[class]来绑定,可以把它改写为绑定到所需 CSS 类名的绑定;这是⼀个或者全有或者全⽆的替换型绑定。
<div>
<div class="color-class" [class]="className">
<p>Test the css class bind</p>
</div>
</div>
这样的话就设置[class]上的类名到div上,class="color-class"会被替换掉。这种⽅式显得太暴⼒了点,可能我只想操作某⼀个class。那么可以使⽤下⾯的⽅式。可以绑定到特定的类名。 当模板表达式的求值结果是真值时,Angular 会添加这个类,反之则移除它。
<div [class.special]="isSpecial">The class binding is special</div>
还有⼀个ngClass内置指令,等到指令篇章学习。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论