ホームページ >ウェブフロントエンド >jsチュートリアル >angular10 でテンプレートにデータ バインディングを実行する方法について話しましょう。
この記事では、angular10 テンプレートのデータ バインディングを紹介し、テンプレート/補間式、属性バインディング、スタイル バインディング、イベント バインディングの 3 つのバインディング構文について説明します。 -way バインディング、組み込み命令、テンプレート参照変数など。
バインディング構文には大きく分けて 3 種類あります (基本)
angular チュートリアル"]
<!-- model => view --> {{expression}} [target]="expression" bind-target="expression" <p> {{ msg }} </p> // 插值表达式 <img [src]="heroImageUrl"> // 属性绑定 <app-hero-detail [hero]="currentHero"></app-hero-detail> // 组件通过属性绑定的方式传参 <div [ngClass]="{'special': isSpecial}"></div> // 样式绑定 <div [class.special]="isSpecial">Special</div> // class绑定 <button [style.color]="isSpecial ? 'red' : 'green'"> // style绑定 <button [attr.aria-label]="help">help</button> // Attribute绑定 <!-- view => model --> (target)="statement" on-target="statement" <button (click)="onSave()">Save</button> // 元素事件 <app-hero-detail (deleteRequest)="deleteHero()"></app-hero-detail> // 组件事件,用于监听子组件传递过来的参数 <div (myClick)="clicked=$event" clickable>click me</div> // 指令事件 <!-- view <=> model --> [(target)]="expression" bindon-target="expression" <input [(ngModel)]="name"> // 双向数据绑定
HTML 属性と DOM プロパティの比較 (非常に重要、理解を深めます)
HTML 属性と DOM 属性の違いを理解することは、Angular バインディングがどのように行われるかを理解することになります。仕事の鍵。属性は HTML によって定義されます。プロパティには、DOM (ドキュメント オブジェクト モデル) ノードからアクセスします。テンプレート バインディングでは、属性の代わりにプロパティとイベントを使用します。
データ バインディングを記述するときは、ターゲット オブジェクトの DOM プロパティとイベントのみを扱います。
注:この一般ルールは、HTML 属性と DOM プロパティのメンタル モデルを構築するのに役立ちます。プロパティは、DOM プロパティの初期化と終了を担当します。プロパティ値は変更できますが、属性値は変更できません。
このルールには例外が 1 つあります。属性は setAttribute() を介して変更でき、対応する DOM 属性が再初期化されます。
ケース 1: input
<input type="text" value="Sarah">ブラウザが入力をレンダリングすると、値 Property が "Sarah " に初期化された対応する DOM ノードが作成されます。 ユーザーが入力に「Sally」と入力すると、DOM 要素の値 Property は Sally になります。ただし、
input.getAttribute('value') を使用して HTML の属性値を表示すると、 属性が変更されていないことがわかります。 結果として Sarah が返されます。
HTML の value 属性は初期値を指定しますが、DOM の value はこのプロパティが現在の値であることを示します。ケース 2: 無効なボタン
disabled 属性は別の例です。ボタンの無効プロパティのデフォルトは false であるため、ボタンは有効になります。 disabled 属性を追加すると、その外観だけでボタンの disabled プロパティが true に初期化されるため、ボタンは無効になります。<button disabled>Test Button</button>無効な属性を追加および削除すると、ボタンが無効になったり有効になったりします。ただし、Attribute の値は重要ではないため、stilldisabled と書いてこのボタンを有効にすることはできません。 ボタンの状態を制御するには、無効なプロパティ
<input [disabled]="condition ? true : false"> <input [attr.disabled]="condition ? 'disabled' : null">
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <p>变量绑定:{{ title }}</p> <p>方法绑定:{{ getVal }}</p> <p>方法绑定:{{ getVal2() }}</p> <p>简单运算 {{ 1 + 1 }}.</p> <p>简单运算 {{ price * 0.7 }}.</p> <p>简单运算:{{ gender === 0 ? '男':'女' }}</p> <p>与方法结合 {{ price * 0.7 + getVal }}.</p> <p>与方法结合 {{ price * 0.7 + getVal2() }}.</p> `, }) export class AppComponent { title = "模板绑定"; price = 30; gender = 0; get getVal(): number { //es6新语法,函数可以当做变量来使用 return 20; } getVal2(): number { return 33; } }テンプレート式を使用する場合は、次のガイドラインに従ってください :
バインディング画像
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <img src="../assets/images/madao.jpg" alt="madao" /> <img [src]="madaoSrc" alt="madao" /> // 推荐 <img bind-src="madaoSrc" alt="madao" /> `, styles: [] }) export class AppComponent { madaoSrc = '../assets/images/madao.jpg'; }
バインディング共通プロパティ
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <img [src]="user.pic" [alt]="user.name" /> <table class="table-bordered"> <tr> <th>name</th> <th>phone</th> <th>age</th> </tr> <tr> <td>张三</td> <td>13398490594</td> <td>33</td> </tr> <tr> <td [colSpan]="colSpan">李四</td> // 注意colSpan和colspan <td>15079049984</td> <td>22</td> </tr> </table> <button class="btn btn-primary" [disabled]="isDisabled">click</button> `, styles: [] }) export class AppComponent { madaoSrc = '../assets/images/madao.jpg'; user = { name: 'madao', pic: this.madaoSrc }; colSpan = 2; isDisabled = false; }
カスタム プロパティをバインドします
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <span [attr.data-title]="customTitle">一行文字</span> <span [attr.title]="customTitle">test title</span> <span [title]="customTitle">test title</span> `, styles: [] }) export class AppComponent { madaoSrc = '../assets/images/madao.jpg'; customTitle = 'bbb'; }
補間式を使用します (推奨されません)
補間は属性でも使用できますが、一般的な方法は角かっこ [] を使用することです。プロジェクト全体で統一されたスタイルを維持することをお勧めします。import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <img src="{{ user.pic }}" alt="{{ user.name }}" /> `, styles: [] }) export class AppComponent { madaoSrc = '../assets/images/madao.jpg'; user = { name: 'madao', pic: this.madaoSrc }; }
単一のスタイルをバインド
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <button type="button" class="btn" [class.btn-primary]="theme === 'primary'">Primary</button> <button type="button" class="btn" [class.btn-secondary]="true">secondary</button> <button type="button" class="btn" [class.btn-success]="isSuccess">success</button> <button type="button" class="btn" [class.btn-danger]="'啦啦啦'">danger</button> <button type="button" class="btn" [class.btn-danger]="0">danger</button> //false <button type="button" class="btn" [class.btn-danger]="undefined">danger</button> //false `, styles: [] }) export class AppComponent { theme = 'primary'; isSuccess = true; }
複数のクラスをバインド
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <button type="button" [class]="btnCls">btnCls</button> <button type="button" [class]="btnCls2">btnCls2</button> <button type="button" [class]="btnCls3">btnCls3</button> <!-- 也可以用内置指令ngClass --> <button type="button" [ngClass]="btnCls">btnCls</button> <button type="button" [ngClass]="btnCls2">btnCls2</button> <button type="button" [ngClass]="btnCls3">btnCls3</button> `, styles: [] }) export class AppComponent { btnCls = 'btn btn-primary'; btnCls2 = ['btn', 'btn-success']; btnCls3 = { btn: true, 'btn-info': true }; }
単一のスタイルをバインド
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <p [style.color]="'#f60'">一段文字</p> <p [style.height]="'50px'" [style.border]="'1px solid'">设置高度</p> <p [style.height.px]="50" [style.border]="'1px solid'">设置高度</p> `, styles: [] }) export class AppComponent {}
複数のスタイルのバインド
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <p [style]="style1">style1</p> <p [style]="style2">style2</p> <p [style]="style3">style3</p> <!-- 也可以用内置指令ngStyle, 但不推荐,以后可能会弃用 --> <!-- <p [ngStyle]="style1">style1</p>--> <!-- <p [ngStyle]="style2">style2</p>--> <!-- ngStyle只接收对象 --> <p [ngStyle]="style3">style3</p> `, styles: [] }) export class AppComponent { style1 = 'width: 200px;height: 50px;text-align: center;border: 1px solid;'; style2 = ['width', '200px', 'height', '50px', 'text-align', 'center', 'border', '1px solid']; // 有问题 style3 = { width: '200px', height: '50px', 'text-align': 'center', border: '1px solid' }; }
バインディングの優先順位
基本的な使い方
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <button type="button" class="btn btn-primary" (click)="onClick()">Primary</button> `, styles: [] }) export class AppComponent { onClick() { console.log('onClick'); } }
事件对象
$event 就是原生的事件对象
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <button type="button" class="btn btn-primary" (click)="onClick($event)">Primary</button> `, styles: [] }) export class AppComponent { onClick(event: MouseEvent) { console.log('onClick', event.target); //直接用event.target.value会报错,要用类型断言 console.log((event.target as HTMLInputElement).value) } }
事件捕获或事件冒泡
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <div style="width:200px;height:200px;background-color:red;" (click)="parentClick()"> <!--<div style="width:100px;height:100px;background-color:blue;" (click)="chilrenClick($event)"></div>--> <div style="width:100px;height:100px;background-color:blue;" (click)="$event.stopPropagation()"></div> //可以在html使用一些简单的语法 </div> `, styles: [] }) export class AppComponent { parentClick() { console.log('parentClick'); } chilrenClick(event: MouseEvent) { event.stopPropagation(); //阻止事件冒泡 console.log('chilrenClick'); } }
输入输出属性(主要是子传父,通过自定义事件)
输入属性
子组件
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-root', template: `<p> Today's item: {{item}} </p>` }) export class ItemDetailComponent { @Input() item: string; }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail [item]="currentItem"></app-item-detail> `, }) export class AppComponent { currentItem = 'Television'; }
输出属性
子组件
import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-root', template: `<label>Add an item: <input #newItem></label> <button (click)="addNewItem(newItem.value)">Add to parent's list</button>`, }) export class ItemOutputComponent { @Output() newItemEvent = new EventEmitter<string>(); //子传父,输出属性 addNewItem(value: string) { this.newItemEvent.emit(value); //自定义事件触发 } }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-output (newItemEvent)="addItem($event)"></app-item-output> //监听自定义事件 `, }) export class AppComponent { items = ['item1', 'item2', 'item3', 'item4']; addItem(newItem: string) { this.items.push(newItem); } }
在元数据中声明输入和输出属性
固然可以在 @Directive 和 @Component 元数据中声明 inputs 和 outputs,但不推荐提供别名
@Input()和@Output()可以接收一个参数,作为变量的别名,那么父组件中只能用别名绑定
子组件
import { Component, Input, EventEmitter, Output } from '@angular/core'; @Component({ selector: 'app-root', template: `<p> Today's item: {{item}} </p>` }) export class ItemDetailComponent { @Input('aliasItem') item: string; @Output('newItem') newItemEvent = new EventEmitter<string>(); addNewItem(value: string) { this.newItemEvent.emit(value); } }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail [aliasItem]="currentItem" //注意是绑定的别名 (newItem)="addItem($event)"></app-item-detail> //注意是监听的别名 `, }) export class AppComponent { currentItem = 'Television'; items = ['item1', 'item2', 'item3', 'item4']; addItem(newItem: string) { this.items.push(newItem); } }
输入属性一定要用中括号[]绑定?
如果绑定的值是静态的,就不需要[];为了统一风格尽量用上[]
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail item="static item"></app-item-detail> `, }) export class AppComponent { // currentItem = 'Television'; }
先决条件
基本的双向绑定
子组件
import {Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, Output} from '@angular/core';@Component({ selector: 'app-sizer', template: ` <div> <button class="btn btn-danger" (click)="dec()" title="smaller">-</button> <button class="btn btn-primary" (click)="inc()" title="bigger">+</button> <label [style.font-size.px]="size">FontSize: {{size}}px</label> </div> `, styles: [ ], changeDetection: ChangeDetectionStrategy.OnPush })export class SizerComponent implements OnInit { @Input() size: number | string; // 想要用双向绑定语法,output变量名就一定是输入属性名加上Change @Output() sizeChange = new EventEmitter<number>(); constructor() { } ngOnInit(): void { } dec() { this.resize(-1); } inc() { this.resize(+1); } resize(delta: number) { this.size = Math.min(40, Math.max(8, +this.size + delta)); this.sizeChange.emit(this.size); } }
父组件
import { Component } from '@angular/core';@Component({ selector: 'app-root', template: ` <app-sizer [(size)]="fontSizePx"></app-sizer> <div [style.font-size.px]="fontSizePx">Resizable Text</div> `, })export class AppComponent { fontSizePx = 16; }
双向绑定工作原理
为了使双向数据绑定有效,@Output() 属性的名字必须遵循 inputChange 模式,其中 input 是相应 @Input() 属性的名字。例如,如果 @Input() 属性为 size ,则 @Output() 属性必须为 sizeChange 。
上面的 sizerComponent 具有值属性 size 和事件属性 sizeChange。 size 属性是 @Input(),因此数据可以流入 sizerComponent 。 sizeChange 事件是一个 @Output() ,它允许数据从 sizerComponent 流出到父组件。
上面例子,有两个方法, dec() 用于减小字体大小, inc() 用于增大字体大小。这两种方法使用 resize() 在最小/最大值的约束内更改 size 属性的值,并发出带有新 size 值的事件。
简写形式
双向绑定语法是属性绑定和事件绑定的组合的简写形式
<app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>
表单中的双向绑定
因为没有任何原生 HTML 元素遵循了 x 值和 xChange 事件的命名模式,所以与表单元素进行双向绑定需要使用 NgModel
基本使用
根据之前基本的双向绑定知识,[(ngModel)]语法可拆解为:
使用[(ngModule)]双向绑定的前提条件是在模块中引入FormsModule
import {Component} from '@angular/core'; @Component({ selector: 'example-app', template: ` <input [(ngModel)]="name" #ctrl="ngModel" required> <p>Value: {{ name }}</p> <p>Valid: {{ ctrl.valid }}</p> <button (click)="setValue()">Set value</button> `, }) export class SimpleNgModelComp { name: string = ''; setValue() { this.name = 'Nancy'; } }
<input [(ngModel)]="name" /> 上面这行代码相当于: <input [value]="name" (input)="name = $event.target.value" />
在表单中的使用
表单中使用[(ngModel)],需要做下面两件事的其中之一
<form> <input [(ngModel)]="value" name="name" /> <input [(ngModel)]="value" [ngModelOptions]="{ standalone: true }" /> </form>
注意:表单中使用双向数据绑定,知识点比较多,这里只做简单了解,后续会出专门章节探讨
循环指令 *ngFor (非常基础,掌握)
arr:string[] = ['张三','李四','王五']; trackByItems(index: number, item: Item): number { return item.id; } <div *ngFor="let item of arr; let i=index" (click)='choseThis(item,i)'> 索引值:{{i}} -- 内容:{{item}} </div> //trackBy一般和长列表一起使用,减少dom替换次数,提升性能 <div *ngFor="let item of items; trackBy: trackByItems"> ({{item.id}}) {{item.name}} </div>
条件渲染 *ngIf ngStyle ngClass ngSwitch(非常基础)
isShow: Boolean = true; personState: number = 2; //频繁切换不建议用,频繁加载和移除有较高的性能消耗 (重要) <p *ngIf="isShow">命令模式</p> // 不频繁切换推荐用 <p [hidden]="isShow">命令模式</p> // 频繁切换推荐用 currentStyles = { 'font-style': this.canSave ? 'italic' : 'normal', 'font-weight': !this.isUnchanged ? 'bold' : 'normal', 'font-size': this.isSpecial ? '24px' : '12px' }; <div [ngClass]="isSpecial ? 'special' : ''">ngClass</div> <div [ngStyle]="currentStyles"> ngStyle </div> // 使用样式有2种(style.dispaly 和 class.hidden) <p [style.display]="isShow?'block':'none'">style模式</p> //频繁切换建议用样式 <p [class.hidden]="isShow">class模式</p> //匹配多种情况的条件渲染,跟vue的v-if/v-else-if/v-else类似 //适合多种状态,显示一种的情况 <div [ngSwitch] = 'personState'> <div *ngSwitchCase="1">工作</div> <div *ngSwitchCase="2">吃饭</div> <div *ngSwitchDefault>睡觉</div> </div>
双向数据绑定指令 [(ngModel)]
//Angular不能直接识别ngModel,需要通过引入模块FormsModule来访问 import {FormsModule} from '@angular/forms'; imports: [FormsModule] public name = "张三"; <input [(ngModel)] = "name" type="text"> //人工绑定,更好的做法是通过响应式表单绑定 <input bindon-change="name" type="text"> //备选 //属性绑定+事件绑定 = ngModel (重要) <input [value]="name" (input)="name=$event.target.value" >
基本使用
使用井号(#)声明模板引用变量,可以获取DOM 元素、指令、组件、TemplateRef 或 Web Component。
import {Component} from '@angular/core'; @Component({ selector: 'app-tpl-var', template: ` <input #phone placeholder="phone number" /> <button (click)="callPhone(phone.value)">Call</button> `, }) export class TplVarComponent { constructor() { } callPhone(value: string) { console.log('callPhone', value); } }
ref
还有种写法就是ref, 下面两种写法是一样的
<input #fax placeholder="fax number" /> <input ref-fax placeholder="fax number" />
引用组件
在组件章节,介绍了获取子组件的属性和方法,有两种方法:本地变量和@viewChild()
import {Component} from '@angular/core'; @Component({ selector: 'app-tpl-var', template: ` <div class="demo-sec"> <button class="btn btn-primary" (click)="sizer.inc()">app inc</button> <app-sizer [(size)]="size" #sizer></app-sizer> size: {{ size }} </div> `, }) export class TplVarComponent { size = 16; constructor() { } }
输入属性
子组件
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-root', template: `<p> Today's item: {{item}} </p>` }) export class ItemDetailComponent { @Input() item: string; }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail [item]="currentItem"></app-item-detail> `, }) export class AppComponent { currentItem = 'Television'; }
输出属性
子组件
import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-root', template: `<label>Add an item: <input #newItem></label> <button (click)="addNewItem(newItem.value)">Add to parent's list</button>`, }) export class ItemOutputComponent { @Output() newItemEvent = new EventEmitter<string>(); addNewItem(value: string) { this.newItemEvent.emit(value); } }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-output (newItemEvent)="addItem($event)"></app-item-output> `, }) export class AppComponent { items = ['item1', 'item2', 'item3', 'item4']; addItem(newItem: string) { this.items.push(newItem); } }
在元数据中声明输入和输出属性
固然可以在 @Directive 和 @Component 元数据中声明 inputs 和 outputs, 不推荐提供别名。
@Input()和@Output()可以接收一个参数,作为变量的别名,那么父组件中只能用别名绑定 子组件
import { Component, Input, EventEmitter, Output } from '@angular/core'; @Component({ selector: 'app-root', template: `<p> Today's item: {{item}} </p>` }) export class ItemDetailComponent { @Input('aliasItem') item: string; // decorate the property with @Input() @Output('newItem') newItemEvent = new EventEmitter<string>(); addNewItem(value: string) { this.newItemEvent.emit(value); } }
父组件
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail [aliasItem]="currentItem" (newItem)="addItem($event)"></app-item-detail> `, }) export class AppComponent { currentItem = 'Television'; items = ['item1', 'item2', 'item3', 'item4']; addItem(newItem: string) { this.items.push(newItem); } }
输入属性一定要用中括号[]绑定?
如果绑定的值是静态的,就不需要[]
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-item-detail item="static item"></app-item-detail> `, }) export class AppComponent { // currentItem = 'Television'; }
常用的管道
1、大小写字母转换
str = 'Hello'; str1 = 'World'; <p>{{str | uppercase}}-{{str1 | lowercase}} </p> //str:hello str1:WORLD
2、 日期格式化(经常使用)
today = new Date(); <p>现在的时间是{{today | date:'yyyy-MM-dd HH:mm:ss'}}</p>
3、保留小数后面多少位 下面例子的含义是,3表示最少几位整数,后面的2-4表示最少最少2位小数,最多4位小数,不足补零,小数会四舍五入。
num = 125.156896; <p>num保留4位小数的值是:{{num | number:'3.2-4'}}</p> //125.1569
4、货币转换
count = 5; price = 1.5; <p>数量:{{count}}</p> // 数据:5 <p>价格:{{price}}</p> // 价格:1.5 <p>总价:{{(price * count) | currency:'¥'}}</p> // 价格:¥7.5
5、字符串截取
name = '只对你说'; <p>{{name | slice : 2 : 4}}</p> // 你说
6、json格式化(有时需要看一下数据)
<p>{{ { name: 'semlinker' } | json }}</p> // { "name": "semlinker" }
自定义管道
1、创建管道文件
ng g pipe /piper/mypiper
2、在管道文件中写自己的逻辑transform两个参数分别表示传入值和参数
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'multiple' }) export class MypiperPipe implements PipeTransform { transform(value: any, args?: any): any { //value:输入值 args:参数 if(!args){//无参的情况下 args = 1; } return value*args; } }
注意:通过命令行生成的管道(过滤器),会自动在全局声明; 管道传入的参数是在':'冒号后面表示
更多编程相关知识,请访问:编程视频!!
以上がangular10 でテンプレートにデータ バインディングを実行する方法について話しましょう。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。