你可以通过把 HTML 模板中的控件绑定到 Angular 组件的属性来显示数据。
要显示组件的属性,最简单的方式就是通过插值表达式 (interpolation
) 来绑定属性名。 要使用插值表达式,就把属性名包裹在双花括号里放进视图模板,如 {{myHero}}
。
删除 index.component.html
文件,这个范例中不再需要它了。然后,到 index.component.ts
文件中修改组件的模板和代码。
修改完之后,它应该是这样的:
index.component.ts
import { Component, OnInit } from '@angular/core';
import as $ from 'jquery';
@Component({
selector: 'app-index',
template: '<nav-public></nav-public>
<div style="margin-top:93px; color: #fff;">
我是首页{{myHero}}
</div>',
styleUrls: ['./index.component.scss']
})
export class IndexComponent implements OnInit {
title = 'Tour of Heroes';
myHero = 'Windstorm';
constructor() {
this.openMenu();
};
ngOnInit() {
}
openMenu(){
$('body').removeClass('noScroll');
if ($('.collapse').hasClass('collapse-active')) {
$('.collapse').removeClass('collapse-active');
$('.collapse').removeClass('collapse-active');
}
else {
$('.collapse').addClass('collapse-active');
}
}
}
效果如下:
这中代入式的模板在大项目中使用可能会遇见小麻烦,维护起来也很糟糕!建议使用templateUrl引入模板
你可以在两种地方存放组件模板。 你可以使用 template 属性把它定义为内联的,或者把模板定义在一个独立的 HTML 文件中, 再通过 @Component 装饰器中的 templateUrl 属性, 在组件元数据中把它链接到组件。
到底选择内联 HTML 还是独立 HTML 取决于个人喜好、具体状况和组织级策略。 上面的应用选择内联 HTML ,是因为模板很小,而且没有额外的 HTML 文件显得这个演示简单些。
无论用哪种风格,模板数据绑定在访问组件属性方面都是完全一样的。
内联模板(template)
模板文件(templateUrl)
虽然这个例子使用了变量赋值的方式初始化组件,你还可以使用构造函数来声明和初始化属性。
export class AppComponent {
title: string;
myHero: string;
constructor() {
this.title = 'Tour of Heroes';
this.myHero = 'Windstorm';
}
}
index.component.ts
import { Component, OnInit } from '@angular/core';
import as $ from 'jquery';
@Component({
selector: 'app-index',
template: <nav-public></nav-public>
<div style="margin-top:93px; color: #fff;">
我是首页{{myHero}}
</div>,
styleUrls: ['./index.component.scss']
})
export class IndexComponent implements OnInit {
title: string;
myHero: string;
heroes: Array;
constructor() {
this.openMenu();
this.title = 'Tour of Heroes';
this.heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
this.myHero = this.heroes[0];
};
ngOnInit() {
}
openMenu(){
$('body').removeClass('noScroll');
if ($('.collapse').hasClass('collapse-active')) {
$('.collapse').removeClass('collapse-active');
$('.collapse').removeClass('collapse-active');
}
else {
$('.collapse').addClass('collapse-active');
}
}
}
效果如图:
应用代码直接在组件内部直接定义了数据。 作为演示还可以,但它显然不是最佳实践。
现在使用的是到了一个字符串数组的绑定。在真实的应用中,大多是到一个对象数组的绑定。
要将此绑定转换成使用对象,需要把这个英雄名字数组变成 Hero 对象数组。但首先得有一个 Hero 类。
执行命令
ng generate class hero
src/app/hero.ts
export class Hero {
constructor(
public id: number,
public name: string) { }
}
你定义了一个类,具有一个构造函数和两个属性:id 和 name。
它可能看上去不像是有属性的类,但它确实有,利用的是 TypeScript 提供的简写形式 —— 用构造函数的参数直接定义属性。
来看第一个参数:
src/app/hero.ts (id)
public id: number,
这个简写语法做了很多:
声明了一个构造函数参数及其类型。
声明了一个同名的公共属性。
当创建该类的一个实例时,把该属性初始化为相应的参数值。
使用 Hero 类
导入了 Hero 类之后,组件的 heroes 属性就可以返回一个类型化的Hero 对象数组了。
src/app/index/index.component.ts (heroes)
heroes = [
new Hero(1, 'Windstorm'),
new Hero(13, 'Bombasto'),
new Hero(15, 'Magneta'),
new Hero(20, 'Tornado')
];
myHero = this.heroes[0];
接着,修改模板。 现在它显示的是英雄的 id 和 name。 要修复它,只显示英雄的 name 属性就行了。
src/app/index/index.component.ts (template)
template: `
<h1>{{title}}</h1>
<h2>My favorite hero is: {{myHero.name}}</h2>
<p>Heroes:</p>
<ul>
<li *ngFor="let hero of heroes">{{ hero.name }}</li>
</ul>`
显示上还和以前一样,不过代码更清晰了。
src/app/index/index.component.ts
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
import { Hero } from '../hero';//引用类
@Component({
selector: 'app-index',
template: ` <nav-public></nav-public>
<div style="margin-top:93px; color: #fff;">我是首页{{myHero}}</div>
<li *ngFor="let hero of heroes" style="color:#f00">{{ hero.name }}</li>`,
styleUrls: ['./index.component.scss']
})
export class IndexComponent implements OnInit {
title: string;
myHero: string;
heroes: Array;
constructor() {
this.openMenu();
this.title = 'Tour of Heroes'; //使用类
this.heroes = [
new Hero(1, 'Windstorm'),
new Hero(13, 'Bombasto'),
new Hero(15, 'Magneta'),
new Hero(20, 'Tornado')
];
this.myHero = this.heroes[0];
};
ngOnInit() { }
openMenu(){
$('body').removeClass('noScroll');
if ($('.collapse').hasClass('collapse-active')) {
$('.collapse').removeClass('collapse-active');
$('.collapse').removeClass('collapse-active');
}
else
{
$('.collapse').addClass('collapse-active');
}
}
}
最终显示结果如图
插值能让你把计算后的字符串合并到 HTML 元素标签之间和属性赋值语句内的文本中。模板表达式则是用来供你求出这些字符串的。
src/app/index/index.component.ts
<div style="margin-top:93px; color: #fff;">
我是首页{{myHero}}
</div>
这个表达式可以调用宿主组件的方法,就像下面用的 getVal():
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
代码如下src/app/index/index.component.ts
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
import { Hero } from '../hero';
@Component({
selector: 'app-index',
template: ` <nav-public></nav-public>
<div style="margin-top:93px; color: #fff;">我是首页{{myHero}}</div>
<li *ngFor="let hero of heroes" style="color:#f00">{{ hero }}</li>
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p> `,
styleUrls: ['./index.component.scss']
})
export class IndexComponent implements OnInit {
title: string;
myHero: string;
heroes: Array;
constructor() {
this.openMenu();
this.title = 'Tour of Heroes';
this.heroes = ['Windstorm1', 'Bombasto2', 'Magneta3', 'Tornado4'];
this.myHero = this.heroes[0];
};
ngOnInit() { }
getVal () { return 2 }
openMenu(){
$('body').removeClass('noScroll');
if ($('.collapse').hasClass('collapse-active')) {
$('.collapse').removeClass('collapse-active');
$('.collapse').removeClass('collapse-active');
}
else
{
$('.collapse').addClass('collapse-active');
}
}
}
Angular 对所有双花括号中的表达式求值,把求值的结果转换成字符串,并把它们跟相邻的字符串字面量连接起来。最后,把这个组合出来的插值结果赋给元素或指令的属性。从表面上看,你就像是在元素标签之间插入了结果并对标签的属性进行了赋值。
模板表达式会产生一个值,并出现在双花括号 {{ }} 中。 Angular 执行这个表达式,并把它赋值给绑定目标的属性,这个绑定目标可能是 HTML 元素、组件或指令。{{1 + 1}} 中所包含的模板表达式是 1 + 1。 在属性绑定中会再次看到模板表达式,它出现在 = 右侧的引号中,就像这样:[property]=”expression”。在语法上,模板表达式与 JavaScript 很像。很多 JavaScript 表达式都是合法的模板表达式,但也有一些例外。你不能使用那些具有或可能引发副作用的 JavaScript 表达式,包括:
赋值 (=, +=, -=, …)
new、typeof、instanceof 等操作符。
使用 ; 或 , 串联起来的表达式
自增和自减运算符:++ 和 —
一些 ES2015+ 版本的操作符
和 JavaScript 语法的其它显著差异包括:
不支持位运算,比如 | 和 &
新的模板表达式运算符,比如 |、?. 和 !。
典型的表达式上下文就是这个组件实例,它是各种绑定值的来源。 在下面的代码片段中,双花括号中的 myHero和引号中的 heroes所引用的都是 IndexComponent 中的属性。
<div style="margin-top:93px; color: #fff;">
我是首页{{myHero}}
</div>
{{ hero }}
表达式的上下文可以包括组件之外的对象。 比如模板输入变量 (let customer)和模板引用变量(#customerInput)就是备选的上下文对象之一。
<ul>
<li *ngFor="let customer of customers">{{customer.name}}</li>
</ul>
<label>Type something:
<input #customerInput>{{customerInput.value}}
</label>
表达式中的上下文变量是由模板变量、指令的上下文变量(如果有)和组件的成员叠加而成的。 如果你要引用的变量名存在于一个以上的命名空间中,那么,模板变量是最优先的,其次是指令的上下文变量,最后是组件的成员。
模板表达式除了目标属性的值以外,不应该改变应用的任何状态。
这条规则是 Angular “单向数据流”策略的基础。 永远不用担心读取组件值可能改变另外的显示值。 在一次单独的渲染过程中,视图应该总是稳定的。
最好使用幂等的表达式,因为它没有副作用,并且能提升 Angular 变更检测的性能。
在 Angular 的术语中,幂等的表达式应该总是返回完全相同的东西,直到某个依赖值发生改变。
在单独的一次事件循环中,被依赖的值不应该改变。 如果幂等的表达式返回一个字符串或数字,连续调用它两次,也应该返回相同的字符串或数字。 如果幂等的表达式返回一个对象(包括 Date 或 Array),连续调用它两次,也应该返回同一个对象的引用。
Angular 会在每个变更检测周期后执行模板表达式。 变更检测周期会被多种异步活动触发,比如 Promise 解析、HTTP 结果、定时器时间、按键或鼠标移动。
表达式应该快速结束,否则用户就会感到拖沓,特别是在较慢的设备上。 当计算代价较高时,应该考虑缓存那些从其它值计算得出的值。
虽然也可以写复杂的模板表达式,不过最好避免那样做。
属性名或方法调用应该是常态,但偶然使用逻辑取反 ! 也是可以的。 其它情况下,应该把应用程序和业务逻辑限制在组件中,这样它才能更容易开发和测试。
代码如下src/app/index/index.component.ts
<button (click)="deleteHero()">Delete hero</button>
export class IndexComponent implements OnInit {
deleteHero () {
console.log('123')
}
}
点击deleteHero控制台会打印出来123
如下图
和表达式中一样,语句只能引用语句上下文中 —— 通常是正在绑定事件的那个组件实例。(click)=”deleteHero()” 中的 deleteHero 就是这个数据绑定组件上的一个方法。
数据绑定是一种机制,用来协调用户所见和应用数据。 虽然你能往 HTML 推送值或者从 HTML 拉取值, 但如果把这些琐事交给数据绑定框架处理, 应用会更容易编写、阅读和维护。 只要简单地在绑定源和目标 HTML 元素之间声明绑定,框架就会完成这项工作。
Angular 提供了各种各样的数据绑定,本章将逐一讨论。 先从高层视角来看看 Angular 数据绑定及其语法。
绑定的类型可以根据数据流的方向分成三类: 从数据源到视图、从视图到数据源以及双向的从视图到数据源再到视图。
数据方向 | 语法 | 绑定类型 |
---|---|---|
单向从数据源到视图 | {{expression}} [target]=”expression” bind-target=”expression” | 插值属性AttributeCSS 类样式 |
从视图到数据源的单向绑定 | (target)=”statement” on-target=”statement” | 事件 |
双向 | [(target)]=”expression” bindon-target=”expression” | 双向 |
数据绑定的目标是 DOM 中的某些东西。 这个目标可能是(元素 | 组件 | 指令的)property、(元素 | 组件 | 指令的)事件,或(极少数情况下) attribute 名。 下面是的汇总表:
绑定类型 | 目标 | 范例 |
---|---|---|
属性 | 元素的 property、组件的 property、指令的 property | <img [src]="heroImageUrl"><app-hero-detail [hero]="currentHero"></app-hero-detail><div [ngClass]="{'special': isSpecial}"></div> |
事件 | 元素的事件、组件的事件、指令的事件 | <button (click)="onSave()">Save</button><app-hero-detail (deleteRequest)="deleteHero()"></app-hero-detail><div (myClick)="clicked=$event" clickable>click me</div> |
双向 | 事件与 property | <input [(ngModel)]="name"> |
Attribute | attribute(例外情况) | <button [attr.aria-label]="help">help</button> |
CSS 类 | class property | <div [class.special]="isSpecial">Special</div> |
样式 | style property | <button [style.color]="isSpecial ? 'red' : 'green'"> |
本文地址:https://www.zhuimengzhu.com/details/211.html
转载地址:暂无
转载说明:转载时请在文首注明来源zhuimengzhu.com 及教程作者,并附本文链接。谢谢各位编辑同仁配合。zhuimengzhu 保留追究相应责任的权利。