Angular 笔记6(组件与模板3)

组件与模板

用户输入

绑定用户输入事件

@Component({
  selector: 'app-click-me',
  template: `
    <button (click)="onClickMe()">Click me!</button>
    {{clickMessage}}`
})
export class ClickMeComponent {
  clickMessage = '';

  onClickMe() {
    this.clickMessage = 'You are my hero!';
  }
}

通过 $event 对象取得用户输入(不靠谱)

template: `
  <input (keyup)="onKey($event)">
  <p>{{values}}</p>
`
export class KeyUpComponent_v1 {
  values = '';
  // 并非所有的event都有value属性
  // onKey(event: any) { // without type info
  //   this.values += event.target.value + ' | ';
  //}
  // 建议转化成正确的类型
  onKey(event: KeyboardEvent) { // with type info
    this.values += (event.target as HTMLInputElement).value + ' | ';
  }
}

通过模板引用变量中获得用户输入

@Component({
  selector: 'app-key-up2',
  template: `
    <input #box (keyup)="onKey(box.value)">
    <p>{{values}}</p>
  `
})
export class KeyUpComponent_v2 {
  values = '';
  onKey(value: string) {
    this.values += value + ' | ';
  }
}

在标识符前加上井号 (#) 就能声明一个模板引用变量。注意应该传递该模板变量的value。

回车事件与失焦事件

@Component({
  selector: 'app-little-tour',
  template: `
    <input #newHero
      (keyup.enter)="addHero(newHero.value)"
      (blur)="addHero(newHero.value); newHero.value='' ">

    <button (click)="addHero(newHero.value)">Add</button>

    <ul><li *ngFor="let hero of heroes">{{hero}}</li></ul>
  `
})
export class LittleTourComponent {
  heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
  addHero(newHero: string) {
    if (newHero) {
      this.heroes.push(newHero);
    }
  }
}

keyup.enter与blur

属性型指令

创建属性型指令

ng generate directive highlight

CLI 会创建 src/app/highlight.directive.ts 及相应的测试文件

使用属性型指令

<p [appHighlight]="color" defaultColor="violet">Highlight me!</p>
export class AppComponent {
  color = 'yellow';
}
import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }
  @Input() defaultColor: string;
  // 绑定到属性别名
  @Input('appHighlight') highlightColor: string;
  
  // @HostListener 装饰器让你订阅某个属性型指令所在的宿主 DOM 元素的事件
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || this.defaultColor || 'red');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}
  1. ElementRef 的 nativeElement 属性可以有直接访问宿主 DOM 元素的能力。
  2. @HostListener 装饰器让你订阅某个属性型指令所在的宿主 DOM 元素的事件
  3. 使用 @Input 数据绑定向指令传递值,还可以指定别名,减少属性的数量
  4. 支持绑定多个属性
    注意此处绑定第二个属性时,没有加上[]方括号,此时就传递的是字符串而不是变量了,该点与Vue中的v-bind(:)很类似。

结构型指令

结构型指令的职责是 HTML 布局。 它们塑造或重塑 DOM 的结构,比如添加、移除或维护这些元素。

结构型指令非常容易识别。 在这个例子中,星号(*)被放在指令的属性名之前。

你可以在一个宿主元素上应用多个属性型指令,但只能应用一个结构型指令。

*ngIf

与v-if差不多,

*ngFor

<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

与v-for用法有些微差别,主要index的获取方式,此处还多了odd(奇数的用法)

模板输入变量与模板引用变量

  • 模板输入变量:可以在单个实例的模板中引用它的值。 上个例子中有好几个模板输入变量:hero、i 和 odd。 它们都是用 let 作为前导关键字。
  • 模板引用变量:使用的是给变量名加 # 前缀的方式(#var)。 一个引用变量引用的是它所附着到的元素、组件或指令。它可以在整个模板的任意位置访问。

每个宿主元素上只能有一个结构型指令

ngIf与ngFor不能同时作用到一个宿主元素上,这点与v-if和v-for相同,都是通过容器包装下,才能在一起使用。

<ng-template>元素

如果没有使用结构型指令,而仅仅把一些别的元素包装进<ng-template> 中,那些元素就是不可见的。

<p>Hip!</p>
<ng-template>
  <p>Hip!</p>
</ng-template>
<p>Hooray!</p>

在这里插入图片描述

<ng-container> 的救赎

Angular 的 <ng-container> 是一个分组元素,但它不会污染样式或元素布局,因为 Angular 压根不会把它放进 DOM 中。
<ng-container>解决了根元素显示异常的情况。

<p>
  I turned the corner
  <ng-container *ngIf="hero">
    and saw {{hero.name}}. I waved
  </ng-container>
  and continued on my way.
</p>

在这里插入图片描述

<div>
  Pick your favorite hero
  (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
</div>
<select [(ngModel)]="hero">
  <ng-container *ngFor="let h of heroes">
    <ng-container *ngIf="showSad || h.emotion !== 'sad'">
      <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
    </ng-container>
  </ng-container>
</select>

在这里插入图片描述

写一个结构型指令(没看懂)

<p>
  The condition is currently
  <span [ngClass]="{ 'a': !condition, 'b': condition, 'unless': true }">{{condition}}</span>.
  <button
    (click)="condition = !condition"
    [ngClass] = "{ 'a': condition, 'b': !condition }" >
    Toggle condition to {{condition ? 'false' : 'true'}}
  </button>
</p>
<p *appUnless="condition" class="unless a">
  (A) This paragraph is displayed because the condition is false.
</p>

<p *appUnless="!condition" class="unless b">
  (B) Although the condition is true,
  this paragraph is displayed because appUnless is set to false.
</p>
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

/**
 * Add the template content to the DOM unless the condition is true.
 */
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
  private hasView = false;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef) { }

  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}

把这个指令添加到 AppModule 的 declarations 数组中。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值