Angular 笔记4(组件与模板1)

显示数据

使用插值显示组件属性

在这里插入图片描述

选择模板来源

  1. 使用 @Component 装饰器的 template 属性来定义内联模板。内联模板对于小型示例或测试很有用。
@Component({
  selector: 'app-root',
  template: `
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero.name}}</h2>
`
})
  1. 可以把模板定义在单独的 HTML 文件中,并且让 @Component 装饰器的 templateUrl 属性指向该文件。这种配置方式通常用于所有比小型测试或示例更复杂的场景中,它也是生成新组件时的默认值。
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

*ngFor 指令

template: `
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero}}</h2>
  <p>Heroes:</p>
  <ul>
    <li *ngFor="let hero of heroes">
      {{ hero }}
    </li>
  </ul>
`

*ngIf 指令

template: `
  <p *ngIf="heroes.length > 3">There are many heroes!</p>
`

Angular 的 ngIf 指令会根据一个布尔条件来显示或移除一个元素。

为数据创建一个类

在这里插入图片描述
在这里插入图片描述

模板语法

插值与模板表达式

插值

<p>{{title}}</p>
<div><img src="{{itemImageUrl}}"></div>

表达式

<img [src]="itemImageUrl2">

<ul>
  <!-- 模板引用变量 -->
  <li *ngFor="let customer of customers">{{customer.name}}		    </li>
</ul>

<label>Type something:
  <!-- 模板引用变量 -->
  <input #customerInput>{{customerInput.value}}
</label>

在这里插入图片描述

模板语句

模板语句出现在 = 号右侧的引号中,就像这样:(event)=“statement”。

<button (click)="deleteHero()">Delete hero</button>
<button (click)="deleteHeroXX('xx')">Delete xx</button>
<button (click)="onSave($event)">Save</button>
<button *ngFor="let hero of heroes" (click)="deleteHero(hero)">{{hero.name}}</button>
<form #heroForm (ngSubmit)="onSubmit(heroForm)"> ... </form>
deleteHero(hero?: Hero) {
  this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
}
deleteHeroXX(str) {
  this.alert(str);
}
onSave(event?: MouseEvent) {
  const evtMsg = event ? (event.target as HTMLElement).textContent : '';
  this.alert(evtMsg);
  if (event) { event.stopPropagation(); }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

绑定语法:概览

Angular 提供了多种数据绑定方式,主要分为三类:
在这里插入图片描述

数据绑定与 HTML

数据绑定的通用规则:数据绑定使用 DOM 元素、组件和指令的 Property,而不是 HTML 的Attribute

<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Save</button>

绑定类型与绑定目标

在这里插入图片描述
在这里插入图片描述

Property 绑定 [property]

单向输入
<img [src]="itemImageUrl">

<!-- Notice the colSpan property is camel case -->
<tr><td [colSpan]="2">Span 2 columns</td></tr>

<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Disabled Button</button>

<p [ngClass]="classes">[ngClass] binding to the classes property making this blue</p>

<app-item-detail [childItem]="parentItem"></app-item-detail>
属性绑定与插值

下列这几对绑定做的事情完全相同:

<p><img src="{{itemImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="itemImageUrl"> is the <i>property bound</i> image.</p>

<p><span>"{{interpolationTitle}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="propertyTitle"></span>" is the <i>property bound</i> title.</p>

attribute、class 和 style 绑定

attribute 绑定

Attribute 绑定的语法类似于 Property 绑定,但其括号之间不是元素的 Property,而是由前缀 attr、点( . )和 Attribute 名称组成。attribute 绑定的主要用例之一是设置 ARIA attribute(译注:ARIA 指无障碍功能,用于给残障人士访问互联网提供便利)。

<!-- create and set an aria attribute for assistive technology -->
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
class 绑定

在这里插入图片描述

style 绑定

在这里插入图片描述

<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>
样式的优先级规则
  • 某个类或样式绑定越具体,它的优先级就越高。
  • 对具体类(例如 [class.foo] )的绑定优先于一般化的 [class] 绑定,对具体样式(例如 [style.bar] )的绑定优先于一般化的 [style] 绑定。
  • 模板中的绑定是最具体的,因为它们直接并且唯一地应用于该元素,所以它们具有最高的优先级。
  • 指令的宿主绑定被认为不太具体,因为指令可以在多个位置使用,所以它们的优先级低于模板绑定。
  • 指令经常会增强组件的行为,所以组件的宿主绑定优先级最低。
  • 绑定总是优先于静态属性。

class 和 [class] 具有相似的具体度,但 [class] 绑定优先,因为它是动态的。

<h3>Dynamic vs static</h3>

<!-- If `classExpr` has a value for the `special` class, this value will override the `class="special"` below -->
<div class="special" [class]="classExpr">Some text.</div>

<!-- If `styleExpr` has a value for the `color` property, this value will override the `style="color: blue"` below -->
<div style="color: blue" [style]="styleExpr">Some text.</div>
委托优先级较低的样式

更高优先级的样式可以使用 undefined 值“委托”给低级的优先级样式。虽然把 style 属性设置为 null 可以确保该样式被移除,但把它设置为 undefined 会导致 Angular 回退到该样式的次高优先级。

<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>

dirWithHostBinding 指令和 comp-with-host-binding 组件都有 [style.width] 宿主绑定。在这种情况下,如果 dirWithHostBinding 把它的绑定设置为 undefined,则 width 属性将回退到 comp-with-host-binding 主机绑定的值。但是,如果 dirWithHostBinding 把它的绑定设置为 null,那么 width 属性就会被完全删除。

事件绑定 (event)

<!-- `myClick` is an event on the custom `ClickDirective` -->
<div>
	<div (myClick)="clickMessage=$event" clickable>click with myClick</div>
	{{clickMessage}}
</div>

,myClick是自定义指令,后续再讲!
在这里插入图片描述

<!-- 注意deleteHero($event)方法中的$event接收了子组件通过EventEmitter暴露的参数 -->
<app-hero-detail (deleteRequest)="deleteHero($event)" [hero]="currentHero"></app-hero-detail>
deleteHero(hero?: Hero) {
  this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
}
// hero-detail子组件
import { Component, EventEmitter, Input, Output } from '@angular/core';

import { Hero } from './hero';

@Component({
  selector: 'app-hero-detail',
  // tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
  inputs: ['hero'],
  outputs: ['deleteRequest'],
  // tslint:enable: no-inputs-metadata-property no-outputs-metadata-property
  styles: ['button {margin-left: 8px} div {margin: 8px 0} img {height:24px}'],
  template: `
  <div>
    <img src="{{heroImageUrl}}">
    <span [style.text-decoration]="lineThrough">
      {{prefix}} {{hero?.name}}
    </span>
    <button (click)="delete()">Delete</button>
  </div>`
})
export class HeroDetailComponent {
  hero: Hero = new Hero(-1, '', 'Zzzzzzzz'); // default sleeping hero
  // heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
  // Public Domain terms of use: http://www.wpclipart.com/terms.html
  heroImageUrl = 'assets/images/hero.png';
  lineThrough = '';
  @Input() prefix = '';

  // This component makes a request but it can't actually delete a hero.
  deleteRequest = new EventEmitter<Hero>();

  delete() {
    this.deleteRequest.emit(this.hero);
    this.lineThrough = this.lineThrough ? '' : 'line-through';
  }
}
$event 和事件处理语句
<div class="parent-div" (click)="onClickMe($event)" clickable>Click me
  <div class="child-div">Click me too!</div>
</div>
onClickMe(event?: MouseEvent) {
  const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className  : '';
  this.alert('Click me.' + evtMsg);
}

点击外层div:
在这里插入图片描述
点击内层div:
在这里插入图片描述
绑定会通过名叫 $event 的事件对象传递关于此事件的信息(包括数据值)。事件对象的形态取决于目标事件。如果目标事件是原生 DOM 元素事件, $event 就是 DOM 事件对象,它有像 target 和 target.value 这样的属性。

<!-- Will save only once -->
<div (click)="onSave()" clickable>
  <button (click)="onSave($event)">Save, no propagation</button>
</div>

<!-- Will save twice -->
<div (click)="onSave()" clickable>
  <button (click)="onSave()">Save w/ propagation</button>
</div>
onSave(event?: MouseEvent) {
  const evtMsg = event ? (event.target as HTMLElement).textContent : '';
  this.alert(evtMsg);
  if (event) { event.stopPropagation(); }
}

如果拿到的是MouseEvent对象,可以阻止事件冒泡。

使用 EventEmitter 实现自定义事件

在这里插入图片描述
在这里插入图片描述

双向绑定 [(…)]

在这里插入图片描述

<div id="two-way-1">
  <app-sizer [(size)]="fontSizePx"></app-sizer>
  <div [style.font-size.px]="fontSizePx">Resizable Text</div>
  <!-- [(ngModel)]需要结合FormsModule一起使用 -->
  <label>FontSize (px): <input [(ngModel)]="fontSizePx"></label>
</div>

在这里插入图片描述
双向绑定会做两件事:

  1. 设置特定的元素属性。
  2. 监听元素的变更事件。

双向绑定语法实际上是属性绑定和事件绑定的语法糖。以上示例可以拆分成:
在这里插入图片描述

内置指令

内置属性型指令

最常见的属性型指令:

  • NgClass —— 添加和删除一组 CSS 类。
  • NgStyle —— 添加和删除一组 HTML 样式。
  • NgModel —— 将数据双向绑定添加到 HTML 表单元素。
NgClass
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
this.currentClasses =  {
  'saveable': this.canSave,
  'modified': !this.isUnchanged,
  'special':  this.isSpecial
};
NgStyle
<div [ngStyle]="currentStyles">
  This div is initially italic, normal weight, and extra large (24px).
</div>
this.currentStyles = {
  'font-style':  this.canSave      ? 'italic' : 'normal',
  'font-weight': !this.isUnchanged ? 'bold'   : 'normal',
  'font-size':   this.isSpecial    ? '24px'   : '12px'
};
[(ngModel)] :双向绑定

在这里插入图片描述
导入 FormsModule 以使用 ngModel
在这里插入图片描述

<input [value]="currentHero.name"
       (input)="updateCurrentHeroName($event)">
without NgModel
<br>
<input [(ngModel)]="currentHero.name">
[(ngModel)]
<br>
<input bindon-ngModel="currentHero.name">
bindon-ngModel
<br>
<input
  [ngModel]="currentHero.name"
  (ngModelChange)="currentHero.name=$event">
(ngModelChange)="...name=$event"
<br>
<input
  [ngModel]="currentHero.name"
  (ngModelChange)="setUppercaseName($event)">
(ngModelChange)="setUppercaseName($event)"
setUppercaseName(name: string) {
  this.currentHero.name = name.toUpperCase();
}

在这里插入图片描述
在这里插入图片描述

内置结构型指令

  • NgIf —— 从模板中创建或销毁子视图。
  • NgFor —— 为列表中的每个条目重复渲染一个节点。
  • NgSwitch —— 一组在备用视图之间切换的指令。
NgIf 与Vue中的v-if指令相似
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
NgFor与Vue中的v-for指令相似
<div *ngFor="let item of items; let i=index">{{i + 1}} - {{item.name}}</div>

带 trackBy 的 *ngFor

<button (click)="changeIds()">Change ids</button>
<div *ngFor="let item of items; trackBy: trackByItems">
  ({{item.id}}) {{item.name}}
</div>
trackByItems(index: number, item: Item): number { 
  return item.id; 
}
changeIds() {
  this.items.forEach(i => {
    if(i.id % 2 == 0) {
      i.id += 2;
    }
  });
}

使用 trackBy,设置需要Angular跟踪的值。这个例子中,该值是英雄的 id,则只有修改了 id 的按钮才会触发元素替换。

NgSwitch 指令

NgSwitch 根据切换条件显示几个可能的元素中的一个。Angular 只会将选定的元素放入 DOM。

NgSwitch 实际上是三个协作指令的集合: ngSwitch,*ngSwitchCase和 *ngSwitchDefault,如以下示例所示。

<div [ngSwitch]="currentItem.feature">
  <app-stout-item    *ngSwitchCase="'stout'"    [item]="currentItem"></app-stout-item>
  <app-device-item   *ngSwitchCase="'slim'"     [item]="currentItem"></app-device-item>
  <app-lost-item     *ngSwitchCase="'vintage'"  [item]="currentItem"></app-lost-item>
  <app-best-item     *ngSwitchCase="'bright'"   [item]="currentItem"></app-best-item>
  <app-unknown-item  *ngSwitchDefault           [item]="currentItem"></app-unknown-item>
</div>

在这里插入图片描述
绑定到 [ngSwitch]。如果试图写成 *ngSwitch,就会出现错误,因为 NgSwitch 是属性型指令,而不是结构型指令。它不会直接接触 DOM,而是会更改与之相伴的指令的行为。

绑定到 *ngSwitchCase 和 *ngSwitchDefault NgSwitchCase 和 NgSwitchDefault 指令都是结构型指令,因为它们会从 DOM 中添加或移除元素。

  • 当 NgSwitchCase 的绑定值等于开关值时,就将其元素添加到 DOM 中;否则从 DOM 中删除。

  • NgSwitchDefault 会在没有任何一个 NgSwitchCase 被选中时把它所在的元素加入 DOM 中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值