数据绑定
- 数据绑定的本质,就是我们的通讯操作
- 左边的业务逻辑.ts 想传递数据给模板显示 .html 可以通过: 插件表达式 {{data}}, 属性绑定 [property]="data"
- 插值表达式 {{data}}
- 变量调用
.html 里写 <p>{{tracyName}} 今年 {{tracyAge}} 岁 <p>
.ts 在 class 里写 export class HerosComponent implements OnInit {
tracyName:String = '飞飞';
tracyAge:Number = 18;
} - 函数调用
.html 里写 <p>{{getTracyName()}} <p>
.ts 在 class 里写 export class HerosComponent implements OnInit {
tracyName:String = '飞飞';
tracyAge:Number = 18;
getTracyName(){return this.tracyName;}
} - 对字符串本身进行输出 {{'值表达式里写的字会直接输入'}}
- 变量调用
- 属性绑定 [property]="data"
- 这个属性必须是空间自带的属性,或者我们自定义的属性,不能乱写
- .html 里写 <button type="button" class="btn btn-primary" [disabled]="shuXingMing">Primary</button>
.ts 在 class 里写 export class HerosComponent implements OnInit {
shuXingMing = true;
constructor() { //构造函数
setTimeout(() => { //设置一个延时操作
this.shuXingMing = false;
}, 2000)
}
- 属性绑定 和 差值表达式的区别:
- 当我们的变量类型是字符串的时候,属性绑定 和 差值表达式是完全一致的。
<img src="{{src}}" />
<img [src]="src" /> 我们还是建议这种 - 当我们的变量是 Boolen, 叠加等, 那么我们就只能使用属性绑定的模式, 否则在 .ts 文件中变量变化的时候, .html 显示的东西不会变
- <button type="button" class="btn btn-primary" [disabled]="shuXingMing">Primary</button>
shuXingMing = true;
- 当我们的变量类型是字符串的时候,属性绑定 和 差值表达式是完全一致的。
- 插值表达式 {{data}}
- 右边的模板显示 .html 想传递数据给 业务逻辑 .ts 需要通过事件处理, 比如 button 的单击事件
- 事件处理 (event) = "expression"
- 单击事件 click
<input type="button" value="按钮" (click)="info()"/> {{tracyName}}
.ts 在 class 里写 export class HerosComponent implements OnInit {
tracyName:String = '飞飞';
info(){
this.tracyName = "11";
}
} - change/input 事件 click
<input type="text" (change)="info($event)"/> {{tracyName}}
.ts 在 class 里写 export class HerosComponent implements OnInit {
tracyName:String = '飞飞';
info(event:any){
//console.log(event);//我们就是通过打印这个 event 在控制台里查看到 这个 文本框输入框里的内容是在 target value 里的
this.tracyName = event.target.value;
this.tracyName = (<HTMLInputElement>event.target).value; // 这里也可以做一个强制转化操作,效果一样
}
}
changge 事件: 此事件会在元素内容发生改变,且失去焦点的时候触发,既在输入结束后点击回车触发
input 事件: 此事件会在 value 属性值发生改变时触发,通过js改变value属性值不会触发此事件。 (input 事件的效果很像双向数据绑定,但是双向数据绑定实现的会更多)
- 双向数据绑定
- 结合两种模式 [(ngModel)] = "data" 通过 ngModel 的方式将数据进行双向数据绑定
这里的中括号,代表属性绑定; 小括号代表事件触发; 那么既绑定属性,又绑定事件就代表我们将逻辑层和模板层做了一个双向绑定 - 双向数据绑定: 变量 tracyName,需在 .ts 文件里的 class 里声明
Input A : <input type="text" [(ngModel)]="tracyName" /> 这里直接显示 {{tracyName}}
在使用 input 标签的时候,需要在 app.module.ts 里引入 form 表单组件 FormsModule
在 "imports:" 对象里加 FormsModule 属性 (加属性之前要往上一个属性的后面加个逗号), 然后在头部加声明 import {FormsModule} from '@angular/forms';
看起来这里很像 事件绑定,文本框里的内容改变,显示出来的 {{tracyName}} 就会变。
但是双向数据绑定意味着,如果 {{tracyName}} 的值变了,这个文本框里的东西也会跟着变, 他们是互相的。
比如说我们加一个上面change 事件写的 Input B: <input type="text" (change)="info($event)"/>
这个 Input B 的内容改变,Input A 也会跟着变。 但是 Input A 改变 则不会硬性 Input B 里的内容。 这才是双向数据绑定的含义。
- 结合两种模式 [(ngModel)] = "data" 通过 ngModel 的方式将数据进行双向数据绑定
指令(Directives)
指令是在 DOM 对象中的一些提示操作,有三种指令
- 使用模板的组件指令
组件指令是三个指令中最常见的, 就是调用组件
.ts 文件的 selector: 'directive-name'
<directive-name></directive-name>
<div directive-name></div>
<div class="directive-name"></div> -
结构指令
- 有一个 * 的前缀 是语法糖的模式
- 在同一个 html 标签里,不能同时进行多个带有 * 号的指令操作,每次只能一个
- 通过添加和移除 DOM 元素来改变 DOM 布局
- 结构指令改变视图的结构,例如 ngfor 和 ngif
- .ts 文件有个 变量 sectionDisplay: false; 然后有个函数可以改变这个变量; html 中可以用 ngif 来让某个 div, p 等标签不渲染 (注意,这里并不是说给隐藏了,而是根本就不渲染,在鼠标右键控制台"检查"的时候 是看不到这段 code 的)
<div *ngIf="sectionDisplay"></div> - ngif 的判断 *ngIf="sellectTab === 'recipes'"
多用于 tab 标签切换, 当 sellectTab = recipes 的时候,相对应的 tab content div 就会显示出来 - 那么有了 ngif, 怎么设定 else 呢?
<div *ngIf="sectionDisplay; else noServer"> Tips: noServer 名字任意</div>
这里要先创建一个 ng-template 然后给它加上一个类似ID 一样的东西 #noServer
<ng-template #noServer><p>else 之后显示的东西 </p></ng-template> - ngFor 循环指令与循环索引
父组件 ts code : servers:['serverTest1','serverTest2','serverTest3'] (如果想添加可以在某个单击事件中写 servers.push(this.变量名))
父组件 html code: <app-recipes-item *ngFor="let server of servers;"></app-recipes-item> 循环显示子组件
注意,这里的 servers 是 ts 文件里的数组名; server 是随便起的,叫 aa 也行 - 给循环设置下标
<app-recipes-item *ngFor="let aa of servers; let i=index"></app-recipes-item>
这里的 i 和 aa 就很方便以后使用,传值给子组件或者属性设置了
比如 : <app-recipes-item *ngFor="let aa of servers; let i=index" [ngStyle]="{backgroundColor: i%2 === 1? '#e0e0e0':'#eee'}"></app-recipes-item> - 结构指令的脱糖操作(removed *)
把指令用方括号阔上, 然后用 ng-template 作为标签
<div *ngIf="sellectTab === 'recipe'">里面有一堆东西</div>
<ng-template [ngIf]="sellectTab === 'recipe'">里面有一堆东西</ng-template>
ngFor 的脱糖
<app-recipe-item *ngFor="let recipeEL of recipes; let i=index" [item]="recipeEL" [index]="i" (selectItem)="onRecipeSelected(recipeEL)"></app-recipe-item>
<ng-template ngFor let-recipeEL [ngForOf]="recipes" let-i="index">
<app-recipe-item [item]="recipeEL" [index]="i" (selectItem)="onRecipeSelected(recipeEL)"></app-recipe-item> </ng-template>
- 自定义结构指定
- 创建自定义结构指令 ng g d name
- <div *ngIf="sellectTab === 'recipe'">结构指定ngIf</div>
<div *appUnless="sellectTab === 'recipe'">自定义结构指定</div>
import { Directive, TemplateRef, Input, ViewContainerRef } from "@angular/core";
@Directive({ selector: "[appUnless]" })
export class UnlessDirective {
@Input() set appUnless(condition: boolean) { if (condition) { this.vcRef.createEmbeddedView(this.templateRef); } else { this.vcRef.clear(); } }
constructor( private templateRef: TemplateRef<any>, private vcRef: ViewContainerRef ) {}
}
-
属性指令
有可能进行数据绑定以及事件绑定- 一个 html 标签上可以设置多个 属性指令
- 更改元素、组件或其他指令的外观或行为,并不更改页面 DOM 结构,即使给隐藏了,它的结构也是可以在鼠标右键控制台"检查"的时候 是看到这段 code 的
- 属性指令作为元素的属性进行设置,例如通过 ngStyle 可以改变元素的样式
- 注意这里的 style 属性和正常的 style 不同,是一个驼峰式的写法
<div [ngStyle]="{backgroundColor: i%2 === 1? '#e0e0e0':'#eee'}"></div> - <div [ngStyle]="{backgroundColor: aa}"></div>
这里的 aa 可以是一个变量名,也可以调用函数 aa(); 都是在 .ts 文件中 - <div [ngClass]="{aa: serverStage === '离线' }"></div>
这里的 aa 是 class 名, 冒号后面是判断,条件为真就用这 class aa, 条件为加就不加这个 class aa.
serverStage 等于 '离线' 的时候 div 用 class="aa" - <li [[ngClass]="{'nav-item': true, 'active': sellectTabName === 'recipes'}">Recipes</li>
多用于 tab 标签切换, navigation 的每个 li 都默认有 nav-item class, 哪个被选中了再加上一个 active class. 这里是 如果 sellectTabName = recipes,相当于<li class="nav-item active">Recipes</li>
- 自定义属性指令
- 创建自定义属性 ng g d name
- 本来后面加 --spec false 是好用的,后来不好用了
- <p appBasicHighlight>自定义属性使用,可以改变背景颜色</p>
import { Directive } from "@angular/core";
import { ElementRef } from "@angular/core";
import { OnInit } from "@angular/core";
@Directive({ selector: "[appBasicHighlight]" })
export class BasicHighlightDirective implements OnInit {
constructor(private elementRef: ElementRef) {}
ngOnInit(): void { this.elementRef.nativeElement.style.backgroundColor = "green"; } } - <p appBetterHighlight> better 自定义属性使用,可以进行元素的渲染操作</p>
import { Directive } from "@angular/core"; import { ElementRef, Renderer2 } from "@angular/core";
import { OnInit } from "@angular/core";
@Directive({ selector : "[appBetterHighlight]" })
export class BetterHighlightDirective implements OnInit { constructor(private elRef: ElementRef, private renderer: Renderer2) {}
ngOnInit(): void { this.renderer.setStyle(this.elRef.nativeElement,'background-color','blue'); } } - 指令监听事件 HostListener,如鼠标划过事件,回车事件等
<p appBetterHighlight> 监听鼠标事件</p>
import { Directive } from "@angular/core";
import { ElementRef, Renderer2 } from "@angular/core";
import { OnInit, HostListener } from "@angular/core";
@Directive({
selector: "[appBetterHighlight]"
})
export class BetterHighlightDirective implements OnInit {
constructor(private elRef: ElementRef, private renderer: Renderer2) {}
//一开始背景颜色是红色
ngOnInit(): void { this.renderer.setStyle( this.elRef.nativeElement, "background-color", "red" ); }
//鼠标滑过,背景颜色是蓝色
@HostListener("mouseenter") mouseover(eventData: Event) { this.renderer.setStyle( this.elRef.nativeElement, "background-color", "blue" ); }
//鼠标滑走,背景颜色变回白色
@HostListener("mouseleave") mouseleave(eventData: Event) { this.renderer.setStyle( this.elRef.nativeElement, "background-color", "white" ); } } - HostBinding 动态设置元素的属性值
<p appBetterHighlight> 监听鼠标事件</p>
@HostBinding('style.backgroundColor') myBackgrounColor:string = "transparent";
//鼠标滑过,背景颜色是蓝色
@HostListener("mouseenter") mouseover(eventData: Event) { this.myBackgrounColor = "blue"; }
//鼠标滑走,背景颜色变回白色
@HostListener("mouseleave") mouseleave(eventData: Event) { this.myBackgrounColor = "transparent" } - 指令的属性绑定 : 动态赋值 <p appBetterHighlight [defaultColor]="'red'" [highlightColor]="'yellow'"> 监听鼠标事件</p>
import { Directive } from "@angular/core";
import { OnInit, HostListener, HostBinding, Input } from "@angular/core";
@Directive({ selector: "[appBetterHighlight]" }) export class BetterHighlightDirective implements OnInit {
constructor() {}
@Input() defaultColor = "transparent";
@Input() highlightColor: string = "blue";
@HostBinding("style.backgroundColor") myBackgrounColor: string = this .defaultColor;
ngOnInit(): void { this.myBackgrounColor = this.defaultColor; }
//鼠标滑过,背景颜色是蓝色
@HostListener("mouseenter") mouseover(eventData: Event) { this.myBackgrounColor = this.highlightColor; }
//鼠标滑走,背景颜色变回白色
@HostListener("mouseleave") mouseleave(eventData: Event) { this.myBackgrounColor = this.defaultColor; } }Tips: 这里可以简化写成
<p [appBetterHighlight]="'yellow'" [defaultColor]="'red'"> 监听鼠标事件</p> @Input('appBetterHighlight') highlightColor: string = "blue";html 也可以简化成 <p appBetterHighlight="yellow" defaultColor="red"> 监听鼠标事件</p>
-
选择指令
<div [ngSwitch]="value">
<p *ngSwitchCase="1">value 值是 1</p>
<p *ngSwitchCase="10">value 值是 10</p>
<p *ngSwitchCase="100">value 值是 100</p>
<p *ngSwitchDefault>value 值是默认值</p>
</div>