整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          AngularJS2 數據顯示—用戶輸入—表單—模板

          AngularJS2 數據顯示—用戶輸入—表單—模板語法大全教程第二章

          ngularJS2 數據顯示

          本章節我們將為大家介紹如何將數據顯示到用戶界面上,可以使用以下三種方式:

          • 通過插值表達式顯示組件的屬性

          • 通過 NgFor 顯示數組型屬性

          • 通過 NgIf 實現按條件顯示


          通過插值表達式顯示組件的屬性

          要顯示組件的屬性,插值是最簡單的方式,格式為:{{屬性名}}。

          以下代碼基于 AngularJS2 TypeScript 環境配置 來創建,你可以再該章節上下載源碼,并修改以下提到的幾個文件。

          app/app.component.ts 文件:

          import{Component}from'@angular/core';@Component({selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>我喜歡的網站: {{mySite}}</h2> `})exportclassAppComponent{title='站點列表'; mySite='菜鳥教程';}

          Angular 會自動從組件中提取 title 和 mySite 屬性的值,并顯示在瀏覽器中,顯示信息如下:

          注意:模板是包在反引號 (`) 中的一個多行字符串,而不是單引號 (')。


          使用 ngFor 顯示數組屬性

          我們也可以循環輸出多個站點,修改以下文件:

          app/app.component.ts 文件:

          import{Component}from'@angular/core';@Component({selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>我喜歡的網站: {{mySite}}</h2> <p>網站列表:</p> <ul> <li *ngFor="let site of sites"> {{site}} </li> </ul> `})exportclassAppComponent{title='站點列表'; sites=['菜鳥教程', 'Google', 'Taobao', 'Facebook']; mySite=this.sites[0];}

          代碼中我們在模板使用 Angular 的 ngFor 指令來顯示 sites 列表中的每一個條目,不要忘記 *ngFor 中的前導星號 (*) 。。

          修改后,瀏覽器顯示如下所示:

          實例中 ngFor 循環了一個數組, 事實上 ngFor 可以迭代任何可迭代的對象。

          接下來我們在 app 目錄下創建 site.ts 的文件,代碼如下:

          app/site.ts 文件:

          exportclassSite{constructor(publicid: number, publicname: string){}}

          以上代碼中定義了一個帶有構造函數和兩個屬性: id 和 name 的類。

          接著我們循環輸出 Site 類的 name 屬性:

          app/app.component.ts 文件:

          import{Component}from'@angular/core';import{Site}from'./site'; @Component({selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>我喜歡的網站: {{mySite.name}}</h2> <p>網站列表:</p> <ul> <li *ngFor="let site of sites"> {{site.name}} </li> </ul> `})exportclassAppComponent{title='站點列表'; sites=[newSite(1, '菜鳥教程'), newSite(2, 'Google'), newSite(3, 'Taobao'), newSite(4, 'Facebook')]; mySite=this.sites[0];}

          修改后,瀏覽器顯示如下所示:


          通過 NgIf 進行條件顯示

          我們可以使用 NgIf 來設置輸出指定條件的數據。

          以下實例中我們判斷如果網站數 3 個以上,輸出提示信息:修改以下 app.component.ts 文件,代碼如下:

          app/app.component.ts 文件:

          import{Component}from'@angular/core';import{Site}from'./site'; @Component({selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>我喜歡的網站: {{mySite.name}}</h2> <p>網站列表:</p> <ul> <li *ngFor="let site of sites"> {{site.name}} </li> </ul> <p *ngIf="sites.length > 3">你有很多個喜歡的網站!</p> `})exportclassAppComponent{title='站點列表'; sites=[newSite(1, '菜鳥教程'), newSite(2, 'Google'), newSite(3, 'Taobao'), newSite(4, 'Facebook')]; mySite=this.sites[0];}

          修改后,瀏覽器顯示如下所示,底部多了個提示信息:

          AngularJS2 用戶輸入

          用戶點擊鏈接、按下按鈕或者輸入文字時,這些用戶的交互行為都會觸發 DOM 事件。

          本章中,我們將學習如何使用 Angular 事件綁定語法來綁定這些事件。

          以下Gif圖演示了該實例的操作:

          源代碼可以再文章末尾下載。


          綁定到用戶輸入事件

          我們可以使用 Angular 事件綁定機制來響應任何 DOM 事件 。

          以下實例將綁定了點擊事件:

          <button (click)="onClickMe()">點我!</button>

          等號左邊的 (click) 表示把該按鈕的點擊事件作為綁定目標 。 等號右邊,引號中的文本是一個 模板語句

          完整代碼如下:

          app/click-me.component.ts 文件:

          import{Component}from'@angular/core'; @Component({selector: 'click-me', template: ` <button(click)="onClickMe()">點我!</button> {{clickMessage}}`})exportclassClickMeComponent{clickMessage=''; onClickMe(){this.clickMessage='菜鳥教程!'; }}


          通過 $event 對象取得用戶輸入

          我們可以綁定到所有類型的事件。

          讓我們試試綁定到一個輸入框的 keyup 事件,并且把用戶輸入的東西回顯到屏幕上。

          app/keyup.component.ts (v1) 文件:

          @Component({selector: 'key-up1', template: ` <input(keyup)="onKey($event)"> <p>{{values}}</p> `})exportclassKeyUpComponent_v1{values=''; /* // 非強類型 onKey(event:any) { this.values +=event.target.value + ' | '; } */// 強類型onKey(event: KeyboardEvent){this.values +=(<HTMLInputElement>event.target).value + ' | '; }}

          以上代碼中我們監聽了一個事件并捕獲用戶輸入,Angular 把事件對象存入 $event 變量中。

          組件的 onKey() 方法是用來從事件對象中提取出用戶輸入的,再將輸入的值累加到 values 的屬性。


          從一個模板引用變量中獲得用戶輸入

          你可以通過使用局部模板變量來顯示用戶數據,模板引用變量通過在標識符前加上井號 (#) 來實現。

          下面的實例演示如何使用局部模板變量:

          app/loop-back.component.ts 文件:

          @Component({selector: 'loop-back', template: ` <input #box(keyup)="0"> <p>{{box.value}}</p> `})exportclassLoopbackComponent{}

          我們在

          <input>

          元素上定義了一個名叫

          box

          的模板引用變量。

          box

          變量引用的就是

          <input>

          元素本身,這意味著我們可以獲得 input 元素的

          value

          值,并通過插值表達式把它顯示在

          <p>

          標簽中。

          我們可以使用模板引用變量來修改以上 keyup 的實例:

          app/keyup.components.ts (v2) 文件:

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


          按鍵事件過濾 ( 通過 key.enter)

          我們可以只在用戶按下回車 (enter) 鍵的時候才獲取輸入框的值。

          (keyup) 事件處理語句會聽到每一次按鍵,我們可以過濾按鍵,比如每一個 $event.keyCode,只有在按下回車鍵才更新 values 屬性。

          Angular 可以為我們過濾鍵盤事件,通過綁定到 Angular 的 keyup.enter 偽事件監聽回車鍵的事件。

          app/keyup.components.ts (v3):

          @Component({selector: 'key-up3', template: ` <input #box(keyup.enter)="values=box.value"> <p>{{values}}</p> `})exportclassKeyUpComponent_v3{values='';}


          blur( 失去焦點 ) 事件

          接下來我們可以使用blur( 失去焦點 ) 事件,它可以再元素失去焦點后更新 values 屬性。

          以下實例同時監聽輸入回車鍵與輸入框失去焦點的事件。

          app/keyup.components.ts (v4):

          @Component({selector: 'key-up4', template: ` <input #box(keyup.enter)="values=box.value"(blur)="values=box.value"> <p>{{values}}</p> `})exportclassKeyUpComponent_v4{values='';}

          AngularJS2 表單

          本章節我們將為大家介紹如何使用組件和模板構建一個 Angular 表單。

          利用 Angular 模板,我們可以創建各種類型表單,例如:登錄表單,聯系人表單,商品詳情表單等,而且我們也為這些表單的字段添加數據校驗。

          接下來我們一步步來實現表單的功能。


          創建項目

          導入初始化項目。

          完整的項目創建可以參考:AngularJS2 TypeScript 環境配置

          創建 Site 模型

          以下創建了一個簡單的模型類 Site,包含了三個必需字段:id,name,url,一個可選字段:alexa。

          在 angular-forms/app 目錄下創建 site.ts 文件,代碼如下:

          app/site.ts 文件:

          exportclassSite{constructor(publicid: number, publicname: string, publicurl: string, publicalexa?: number){}}

          以下代碼中,標為 public 的為公有字段,alexa 后添加一個問號(?)表示可選字段。

          創建一個表單組件

          每個 Angular 表單分為兩部分:一個基于 HTML 的模板,和一個基于代碼的組件,它用來處理數據和用戶交互。

          在 angular-forms/app 目錄下創建 site-form.component.ts 文件,代碼如下:

          app/site-form.component.ts 文件:

          import{Component}from'@angular/core';import{Site}from'./site'; @Component({moduleId: module.id, selector: 'site-form', templateUrl: 'site-form.component.html'})exportclassSiteFormComponent{urls=['www.runoob.com', 'www.google.com', 'www.taobao.com', 'www.facebook.com']; model=newSite(1, '菜鳥教程', this.urls[0], 10000); submitted=false; onSubmit(){this.submitted=true; }// TODO: 完成后移除getdiagnostic(){returnJSON.stringify(this.model); }}

          實例中導入了 Component 裝飾器和 Site 模型。

          @Component 選擇器 "site-form" 表示我們可以通過一個 <site-form> 標簽,把此表單扔進父模板中。

          templateUrl 屬性指向一個獨立的HTML模板文件,名叫 site-form.component.html。

          diagnostic 屬性用于返回這個模型的JSON形式。

          定義應用的根模塊

          修改 app.module.ts 來定義應用的根模塊,模塊可中指定了引用到的外部及聲明屬于本模塊中的組件,比如 SiteFormComponent。

          因為模板驅動的表單有它們自己的模塊,所以我們得把 FormsModule 添加到本應用的 imports 數組中,這樣我們才能使用表單。

          app/app.module.ts 文件代碼如下

          app/app.module.ts 文件:

          import{NgModule}from'@angular/core';import{BrowserModule}from'@angular/platform-browser';import{FormsModule}from'@angular/forms';import{AppComponent}from'./app.component';import{SiteFormComponent}from'./site-form.component'; @NgModule({imports: [BrowserModule, FormsModule], declarations: [AppComponent, SiteFormComponent], bootstrap: [AppComponent]})exportclassAppModule{}

          創建根組件

          修改根組件文件 app.component.ts,將 SiteFormComponent 將被放在其中。

          app/app.component.ts 文件:

          import{Component}from'@angular/core'; @Component({selector: 'my-app', template: '<site-form></site-form>'})exportclassAppComponent{}

          創建一個初始 HTML 表單模板

          創建模板文件 site-form.component.html ,代碼如下所示:

          app/site-form.component.html 文件:

          <divclass="container"><h1>網站表單</h1><form><divclass="form-group"><labelfor="name">網站名</label><inputtype="text"class="form-control"id="name"required></div><divclass="form-group"><labelfor="alterEgo">alexa 排名</label><inputtype="text"class="form-control"id="alexa"></div><buttontype="submit"class="btn btn-default">提交</button></form></div>

          required 屬性設置的該字段為必需字段,如果沒有設置則是可選。

          在 angular-forms 目錄下輸入以下命令:

          cnpm install bootstrap --save

          打開 index.html 文件,把以下樣式鏈接添加到 <head> 中:

          <linkrel="stylesheet"href="node_modules/bootstrap/dist/css/bootstrap.min.css">

          執行 npm start 后,訪問:http://localhost:3000/,輸出效果如下:


          使用 ngModel 進行雙向數據綁定

          接下來我們使用 ngModel 進行雙向數據綁定,通過監聽 DOM 事件,來實現更新組件的屬性。

          修改 app/site-form.component.html ,使用 ngModel 把我們的表單綁定到模型。代碼如下所示:

          app/site-form.component.html 文件:

          <divclass="container"><h1>網站表單</h1><form> {{diagnostic}} <divclass="form-group"><labelfor="name">網站名</label><inputtype="text"class="form-control"id="name"required [(ngModel)]="model.name"name="name"></div><divclass="form-group"><labelfor="alexa">alexa 排名</label><inputtype="text"class="form-control"id="alexa" [(ngModel)]="model.alexa"name="alexa"></div><divclass="form-group"><labelfor="url">網站 URL </label><selectclass="form-control"id="url"required [(ngModel)]="model.url"name="url"><option *ngFor="let p of urls" [value]="p">{{p}}</option></select></div><buttontype="submit"class="btn btn-default">提交</button></form></div>

          • 每一個 input 元素都有一個 id 屬性,它被 label 元素的 for 屬性用來把標簽匹配到對應的 input 。

          • 每一個 input 元素都有一個 name 屬性, Angular 的表單模塊需要使用它為表單注冊控制器。

          運行以上實例輸出結果如下:

          {{diagnostic}} 只是用于測試時候輸出數據使用。

          我們還可以通過 ngModel 跟蹤修改狀態與有效性驗證,它使用了三個 CSS 類來更新控件,以便反映當前狀態。

          狀態為 true 時的類為 false 時的類
          控件已經被訪問過ng-touchedng-untouched
          控件值已經變化ng-dirtyng-pristine
          控件值是有效的ng-validng-invalid

          這樣我們就可以添加自定義 CSS 來反應表單的狀態。

          在 angular-forms 目錄下創建 forms.css 文件,代碼如下:

          forms.css 文件:

          .ng-valid[required], .ng-valid.required{border-left:5pxsolid#42A948; /* green */}.ng-invalid:not(form) {border-left:5pxsolid#a94442; /* red */}

          打開 index.html 文件,把以下樣式鏈接添加到 <head> 中:

          <linkrel="stylesheet"href="forms.css">

          修改 app/site-form.component.html ,代碼如下所示:

          app/site-form.component.html 文件:

          <divclass="container"><h1>網站表單</h1><form> {{diagnostic}} <divclass="form-group"><labelfor="name">網站名</label><inputtype="text"class="form-control"id="name"required [(ngModel)]="model.name"name="name" #name="ngModel"><div [hidden]="name.valid || name.pristine"class="alert alert-danger"> 網站名是必需的 </div></div><divclass="form-group"><labelfor="alexa">alexa 排名</label><inputtype="text"class="form-control"id="alexa" [(ngModel)]="model.alexa"name="alexa"></div><divclass="form-group"><labelfor="url">網站 URL </label><selectclass="form-control"id="url"required [(ngModel)]="model.url"name="url"><option *ngFor="let p of urls" [value]="p">{{p}}</option></select></div><buttontype="submit"class="btn btn-default">提交</button></form></div>

          模板中通過把 div 元素的 hidden 屬性綁定到 name 控件的屬性,我們就可以控制"name"字段錯誤信息的可見性了。

          刪除掉 name 字段的數據,顯示結果如下所示:

          添加一個網站

          接下來我們創建一個用于添加網站的表單,在 app/site-form.component.html 添加一個按鈕:

          app/site-form.component.html 文件:

          <buttontype="button"class="btn btn-default" (click)="newSite()">添加網站</button>

          將以上按鈕事件綁定到組件方法上:

          app/site-form.component.ts 文件:

          active=true; newSite(){this.model=newSite(5, '', ''); this.active=false; setTimeout(()=> this.active=true, 0);}

          我們給組件添加一個 active 標記,把它初始化為 true 。當我們添加一個新的網站時,它把 active 標記設置為 false , 然后通過一個快速的 setTimeout 函數迅速把它設置回 true 。

          通過 ngSubmit 來提交表單

          我們可以使用 Angular 的指令 NgSubmit 來提交表單, 并且通過事件綁定機制把它綁定到 SiteFormComponent.submit() 方法上。

          <form *ngIf="active" (ngSubmit)="onSubmit()" #siteForm="ngForm">

          我們定義了一個模板引用變量 #siteForm ,并且把它初始化為 "ngForm" 。

          這個 siteForm 變量現在引用的是 NgForm 指令,它代表的是表單的整體。

          site-form.component.ts 文件完整代碼如下:

          app/site-form.component.ts 文件:

          import{Component}from'@angular/core';import{Site}from'./site'; @Component({moduleId: module.id, selector: 'site-form', templateUrl: 'site-form.component.html'})exportclassSiteFormComponent{urls=['www.runoob.com', 'www.google.com', 'www.taobao.com', 'www.facebook.com']; model=newSite(1, '菜鳥教程', this.urls[0], 10000); submitted=false; onSubmit(){this.submitted=true; }// TODO: 完成后移除getdiagnostic(){returnJSON.stringify(this.model); }active=true; newSite(){this.model=newSite(5, '', ''); this.active=false; setTimeout(()=> this.active=true, 0); }}

          app/site-form.component.html 完整代碼如下:

          app/site-form.component.html 文件:

          <divclass="container"><div [hidden]="submitted"><h1>網站表單</h1><form *ngIf="active" (ngSubmit)="onSubmit()" #siteForm="ngForm"> {{diagnostic}} <divclass="form-group"><labelfor="name">網站名</label><inputtype="text"class="form-control"id="name"required [(ngModel)]="model.name"name="name" #name="ngModel"><div [hidden]="name.valid || name.pristine"class="alert alert-danger"> 網站名是必需的 </div></div><divclass="form-group"><labelfor="alexa">alexa 排名</label><inputtype="text"class="form-control"id="alexa" [(ngModel)]="model.alexa"name="alexa"></div><divclass="form-group"><labelfor="url">網站 URL </label><selectclass="form-control"id="url"required [(ngModel)]="model.url"name="url"><option *ngFor="let p of urls" [value]="p">{{p}}</option></select></div><buttontype="submit"class="btn btn-default" [disabled]="!siteForm.form.valid">提交</button><buttontype="button"class="btn btn-default" (click)="newSite()">新增網站</button></form></div><div [hidden]="!submitted"><h2>你提交的信息如下:</h2><divclass="row"><divclass="col-xs-3">網站名</div><divclass="col-xs-9 pull-left">{{ model.name }}</div></div><divclass="row"><divclass="col-xs-3">網站 alexa 排名</div><divclass="col-xs-9 pull-left">{{ model.alexa }}</div></div><divclass="row"><divclass="col-xs-3">網站 URL </div><divclass="col-xs-9 pull-left">{{ model.url }}</div></div><br><buttonclass="btn btn-default" (click)="submitted=false">編輯</button></div></div>

          模板中我們把 hidden 屬性綁定到 SiteFormComponent.submitted 屬性上。

          主表單從一開始就是可見的,因為 submitted 屬性是 false ,當我們提交了這個表單則隱藏,submitted 屬性是 true:

          submitted=false; onSubmit(){this.submitted=true; }

          最終的目錄結構為:

          AngularJS2 模板語法

          前面幾個章節我們已經接觸了 Angular 的模板,本文我們將具體介紹 Angular 的語法使用。

          模板扮演的是一個視圖的角色,簡單講就是展示給用戶看的部分。

          • HTML

          • 插值表達式

          • 模板表達式

          • 模板語句

          • 綁定語法

          • 屬性綁定

          • HTML 屬性、 class 和 style 綁定

          • 事件綁定

          • 使用 NgModel 進行雙向數據綁定

          • 內置指令

          • * 與 <template>

          • 模板引用變量

          • 輸入輸出屬性

          • 模板表達式操作符


          HTML

          HTML 是 Angular 模板的"語言",除了 <script> 元素是被禁用的外 ,其他 HTML 元素都是支持的,例如:

          <h1>我的第一個 Angular 應用</h1>


          插值表達式

          插值表達式的語法格式為:{{ ... }}。

          插值表達式可以把計算的字符串插入HTML中,也可以作為屬性值來使用。

          <h3> {{title}} <imgsrc="{{imageUrl}}"style="height:30px"></h3>


          模板表達式

          {{ ... }} 里頭其實就是一個模板表達式,Angular 會對其進行求值并轉化為字符串輸出。

          以下實例是兩個數相加:

          <!-- "The sum of 1 + 1 is 2" --><p>The sum of 1 + 1 is {{1 + 1}}</p>

          我們可以使用 getVal() 來獲取這個表達式的值:

          <divclass="example"><divclass="example_code">[mycode3 type="html"]<!-- "4" --><p>{{1 + 1 + getVal()}}</p>

          模板表達式類似 JavaScript 的語言,很多 JavaScript 表達式也是合法的模板表達式,但不是全部。

          以下 JavaScript 表達式是禁止的:

          • 賦值表達式(

            =

            ,

            +=

            ,

            -=

            ...)
          • new操作符

          • 帶有

            ;

            或者

            '

            的連接表達式
          • 自增和自減操作(

            ++

            --

            ) 其他與Javascript語法不同的值得注意的包括:
          • 不支持位運算符(

            |

            &

          • 模板表達式的操作符,如

            |

            ?.

            等,被賦予了新的含義

          屬性綁定

          模板的屬性綁定可以把視圖元素的屬性設置為模板表達式 。

          最常用的屬性綁定是把元素的屬性設置為組件中屬性的值。 下面這個例子中, image 元素的 src 屬性會被綁定到組件的 imageUrl 屬性上:

          <img [src]="imageUrl">

          當組件為 isUnchanged( 未改變 ) 時禁用一個按鈕:

          <button [disabled]="isUnchanged">按鈕是禁用的</button>

          設置指令的屬性:

          <div [ngClass]="classes">[ngClass]綁定到classes 屬性</div>

          設置一個自定義組件的屬性(這是父子組件間通訊的重要途徑):

          <user-detail [user]="currentUser"></user-detail>


          HTML 屬性(Attribute)、 class 和 style 綁定

          模板語法為那些不太適合使用屬性綁定的場景提供了專門的單向數據綁定形式。

          屬性(Attribute)、綁定

          當元素沒有屬性可綁的時候,使用HTML標簽屬性(Attribute)綁定。

          考慮 ARIA, SVG 和 table 中的 colspan/rowspan 等屬性(Attribute) 。它們是純粹的屬性 。 它們沒有對應的屬性可供綁定。

          以下實例會報錯:

          <tr><tdcolspan="{{1 + 1}}">Three-Four</td></tr>

          我們會得到這個錯誤:

          Template parse errors:Can't bind to 'colspan' since it isn't a known native property模板解析錯誤:不能綁定到'colspan',因為它不是已知的原生屬性

          正如提示中所說,

          <td>

          元素沒有

          colspan

          屬性。 但是插值表達式和屬性綁定只能設置 屬性 ,而不是 Attribute,所以需HTML標簽 Attribute 綁定來創建和綁定類似的Attribute。

          HTML標簽特性綁定在語法上類似于屬性綁定,但中括號中的部分不是一個元素的屬性名,而是由一個attr.的前綴和HTML標簽屬性的名稱組成,然后通過一個能求值為字符串的表達式來設置HTML標簽屬性的值。如:

          <tableborder=1><tr><td [attr.colspan]="1 + 1">One-Two</td></tr><tr><td>Five</td><td>Six</td></tr></table>

          css類綁定

          借助 CSS 類綁定 ,我們可以從元素的 class 屬性上添加和移除 CSS 類名。

          CSS 類綁定在語法上類似于屬性綁定。但方括號中的部分不是一個元素的屬性名,而是包括一個 class 前綴,緊跟著一個點 (.) ,再跟著 CSS 類的名字組成。 其中后兩部分是可選的。例如: [class.class-name]

          下面的例子展示了如何通過css類綁定類添加和移除"special"類:

          <!-- 標準HTML樣式類設置 --><divclass="bad curly special">Bad curly special</div><!-- 通過綁定重設或覆蓋樣式類 --><divclass="bad curly special" [class]="badCurly">Bad curly</div><!-- 通過一個屬性值來添加或移除special樣式類 --><div [class.special]="isSpecial">這個樣式比較特殊</div>

          style樣式綁定

          通過樣式綁定,可以設置內聯樣式。樣式綁定語法上類似于屬性綁定,但中括號里面的部分不是一個元素的屬性名,樣式綁定包括一個style.,緊跟著css樣式的屬性名,例如:[style.style-property]。

          <button [style.color]="isSpecial ? 'red': 'green'">紅色</button><button [style.background-color]="canSave ? 'cyan': 'grey'">保存</button><!-- 帶有單位的樣式綁定 --><button [style.font-size.em]="isSpecial ? 3 : 1">大</button><button [style.font-size.%]="!isSpecial ? 150 : 50">小</button>

          樣式屬性可以是中線命名法(font-size),也可以是駝峰是命名法(fontSize)。


          事件綁定

          在事件綁定中,Angular通過監聽用戶動作,比如鍵盤事件、鼠標事件、觸屏事件等來響應相對應的數據流向-從視圖目標到數據源。

          事件綁定的語法是由等號左側小括號內的 目標事件 和右側引號中的 模板聲明 組成。

          比如下面這個例子,是事件綁定監聽按鈕的點擊事件。只要點擊鼠標,都會調用組件的 onSave()方法。

          <button (click)="onSave()">保存</button>

          圓括號中的名稱 ——比如 (click) ——標記出了目標事件。在下面這個例子中,目標是按鈕的 click 事件。

          <button (click)="onSave()">Save</button>

          也可以使用on- 前綴的形式:

          <buttonon-click="onSave()">On Save</button>


          使用 NgModel 進行雙向數據綁定

          當開發數據輸入表單時,期望的結果是既能將組件的數據顯示到表單上,也能在用戶修改時更新組件的數據。

          以下是一個通過 [(NgModel)] 來實現雙向綁定:

          <input [(ngModel)]="currentUser.firstName">

          []實現了數據流從組件到模板,()實現了數據流從模板到組件,兩者一結合[()]就實現了雙向綁定。

          使用前綴形式的語法:

          <inputbindon-ngModel="currentUser.firstName">


          內置指令

          Angular 的內置指令有 NgClass、NgStyle、NgIf、NgFor、NgSwitch等。

          NgClass

          通過綁定到 NgClass 動態添加或刪除 CSS 類。

          <div [style.font-size]="isSpecial ? 'x-large' : 'smaller'"> 這個div是大號的。</div>

          NgStyle

          NgStyle 通過把它綁定到一個key:value控制對象的形式,可以讓我們同時設置很多內聯樣式。

          setStyles() { let styles={ // CSS屬性名 'font-style': this.canSave ? 'italic' : 'normal', // italic 'font-weight': !this.isUnchanged ? 'bold' : 'normal', // normal 'font-size': this.isSpecial ? '24px' : '8px', // 24px }; return styles;}

          通過添加一個NgStyle屬性綁定,讓它調用setStyles,并據此來設置元素的樣式:

          <div [ngStyle]="setStyles()"> 這個div的樣式是italic, normal weight, 和extra large (24px)。</div>

          NgIf

          通過把NgIf指令綁定到一個真值表達式,可以把一個元素及其子元素添加到DOM樹上。

          <div *ngIf="currentUser">Hello,{{currentUser.firstName}}</div>

          相反,綁定到一個假值表達式將從DOM樹中移除該元素及其子元素。如:

          <!-- 因為isActive的值為false,所以User Detail不在DOM樹種--><user-detail *ngIf="isActive"></user-detail>

          NgSwitch

          當需要從一組可能的元素樹中根據條件顯示其中一個時,就需要NgSwitch了。Angular將只把選中的元素添加進DOM中。如:

          <span [ngSwitch]="userName"><span *ngSwitchCase="'張三'">張三</span><span *ngSwitchCase="'李四'">李四</span><span *ngSwitchCase="'王五'">王五</span><span *ngSwitchCase="'趙六'">趙六</span><span *ngSwitchDefault>龍大</span></span>

          把作為父指令的

          NgSwitch

          綁定到一個能返回開關值的表達式,例子中這個值是字符串,但它可以是任何類型的值。父指令

          NgSwitch

          控制一組

          <span>

          子元素。每個

          <span>

          或者掛在一個匹配值的表達式上,或者被標記為默認情況。任何時候,這些span中最多只有一個會出現在DOM中。如果這個span的匹配值和開關值相等,Angular2就把這個

          <span>

          添加DOM中。如果沒有任何span匹配上,Angular2就會把默認的span添加到DOM中。Angular2會移除并銷毀所有其他的span。

          三個相互合作的指令:

          • ngSwitch:綁定到一個返回開關值的表達式

          • ngSwitchCase:綁定到一個返回匹配值的表達式

          • ngSwitchDefault:一個用于標記默認元素的屬性 注意:不要再ngSwitch前使用

            *

            ,而應該用屬性綁定,但ngSwitchCase和ngSwitchDefault前面要放

            *

          NgFor

          當需要展示一個由多個條目組成的列表時就需要這個指令了。如下面這個例子,就是在一個HTML塊上應用NgFor。

          <div *ngFor="let user of users">{{user.fullName}}</div>

          NgFor也可以應用在一個組件元素上,如:

          <user-detail *ngFor="let user of users" [user]="user"></user-detail>

          ngFor指令支持一個可選的index索引,在迭代過程中會從0增長到數組中的長度。

          可以通過模板輸入變量來捕獲這個index,并應用在模板中。下面的例子就把index捕獲到了一個名為i的變量中。

          <div *ngFor="let user of users; let i=index">{{i + 1}} - {{user.fullName}}</div>

          NgForTrackBy

          ngFor 指令有時候會性能較差,特別是在大型列表中。 對一個條目的一點小更改、移除或添加,都會導致級聯的 DOM 操作。

          比如,當通過重新從服務器來刷新通訊錄,刷新后的列表可能包含很多(如果不是全部的話)以前顯示過的聯系人。但在Angular看來,它不知道哪些是以前就存在過的,只能清理舊列表、舍棄那些DOM元素,并用新的DOM元素來重建一個新列表。

          解決這個問題,可以通過追蹤函數來避免這種折騰。追蹤函數會告訴Angular:我們知道兩個具有相同user.id的對象是同一個聯系人。如:

          trackByUsers(index: number, user: User){return user.id}

          然后,把NgForTrackBy指令設置為那個追蹤函數:

          <div *ngFor="let user of users; trackBy:trackByUsers">({{user.id}}) {{user.fullName}}</div>

          追蹤函數不會排除所有DOM更改。如果用來判斷是否為同一個聯系人的屬性變化了,就會更新DOM元素,反之就會留下這個DOM元素。列表界面就會變得比較更加平滑,具有更好的響應效果。


          模板引用變量

          模板引用變量是模板中對 DOM 元素或指令的引用。

          它能在原生 DOM 元素中使用,也能用于 Angular 組件——實際上,它可以和任何自定義 Web 組件協同工作。

          我們可以在同一元素、兄弟元素或任何子元素中引用模板引用變量。

          這里是關于創建和使用模板引用變量的兩個例子:

          <!-- phone 引用了 input 元素,并將 `value` 傳遞給事件句柄 --><input #phoneplaceholder="phone number"><button (click)="callPhone(phone.value)">Call</button><!-- fax 引用了 input 元素,并將 `value` 傳遞給事件句柄 --><inputref-faxplaceholder="fax number"><button (click)="callFax(fax.value)">Fax</button>

          "phone" 的 (#) 前綴意味著我們將要定義一個 phone 變量。

          相關文章

          https://gf-rd.gitbooks.io/angular-2-step-by-step/content/chapters/2.3.html

          件注冊

          定義好的組件需要注冊才能被使用。 注冊方式有兩種

          1. 全局注冊
          2. 局部注冊

          全局注冊

          .component() 方法,讓組件在當前 Vue 應用中全局可用。 在 main.ts 中

          import './assets/main.css'
          
          import { createApp } from 'vue'
          import { createPinia } from 'pinia'
          import GlobalTitle from '@/components/GlobalTitle.vue'
          
          
          import App from './App.vue'
          import router from './router'
          
          const app=createApp(App)
          
          app.component('GlobalTitle', GlobalTitle)
          
          app.use(createPinia())
          app.use(router)
          
          app.mount('#app')
          
          

          在 vue 中直接使用無需導入

          <script lang="ts" setup>
          import { ref } from 'vue'
          </script>
          
          <template>
            <div class="container">
              <GlobalTitle></GlobalTitle>
            </div>
          </template>
          
          <style lang="scss" scoped>
          .container {
          }
          </style>
          
          

          效果:

          全局注冊的組件可以在此應用的任意組件的模板中使用,所有的子組件也可以使用全局注冊的組件。

          全局組件缺點

          • 全局注冊,但并沒有被使用的組件無法在生產打包時被自動移除 (也叫“tree-shaking”)。如果你全局注冊了一個組件,即使它并沒有被實際使用,它仍然會出現在打包后的 JS 文件中。
          • 全局注冊在大型項目中使項目的依賴關系變得不那么明確。在父組件中使用子組件時,不太容易定位子組件的實現。和使用過多的全局變量一樣,這可能會影響應用長期的可維護性。

          局部注冊

          局部注冊的組件需要在使用它的父組件中顯式導入,并且只能在該父組件中使用。

          它的優點是使組件之間的依賴關系更加明確,并且對 tree-shaking 更加友好。

          定義組件

          <script lang="ts" setup>
          import { ref } from 'vue'
          </script>
          
          <template>
            <div class="container">
              <h2>這是一個局部組件</h2>
            </div>
          </template>
          
          <style lang="scss" scoped>
          .container {
          }
          </style>
          
          

          局部使用組件

          <script lang="ts" setup>
          import { ref } from 'vue'
          import PartTitle from '@/components/PartTitle.vue'
          </script>
          
          <template>
            <div class="container">
              <PartTitle />
            </div>
          </template>
          
          <style lang="scss" scoped>
          .container {
          }
          </style>
          
          

          組件名格式

          推薦 PascalCase 作為組件名的注冊格式。

          1. PascalCase 是合法的 JavaScript 標識符。這使得在 JavaScript 中導入和注冊組件都很容易,同時 IDE 也能提供較好的自動補全。
          2. <PascalCase /> 在模板中更明顯地表明了這是一個 Vue 組件,而不是原生 HTML 元素。同時也能夠將 Vue 組件和自定義元素 (web components) 區分開來。

          在單文件組件和內聯字符串模板中,我們都推薦這樣做。

          為了方便,Vue 支持將模板中使用 kebab-case 的標簽解析為使用 PascalCase 注冊的組件。

          這意味著一個以 MyComponent 為名注冊的組件,在模板中可以通過 <MyComponent> 或 <my-component> 引用。這讓我們能夠使用同樣的 JavaScript 組件注冊代碼來配合不同來源的模板。

          props

          Props 聲明

          一個組件需要顯式聲明它所接受的 props,這樣 Vue 才能知道外部傳入的哪些是 props,哪些是透傳 attribute。

          setup 寫法

          組件定義

          <script lang="ts" setup>
          import { ref } from 'vue'
          
          const props=defineProps(['person'])
          </script>
          
          <template>
            <div class="container">
              <h1>{{ props.person }}</h1>
            </div>
          </template>
          
          <style lang="scss" scoped>
          .container {
          }
          </style>
          

          組件使用

          <script lang="ts" setup>
          import { ref } from 'vue'
          import Com14 from '@/components/Com14.vue'
          </script>
          
          <template>
            <div class="container">
              <Com14 person="'王大可'" />
            </div>
          </template>
          
          <style lang="scss" scoped>
          .container {
          }
          </style>
          

          聲明對象形式的屬性 setup JavaScript 形式

          defineProps({
            title: String,
            likes: Number
          })
          

          setup TypeScript 形式

          <script setup lang="ts">
          defineProps<{
            title?: string
            likes?: number
          }>()
          </script>
          
          

          對象形式的 props 聲明不僅可以一定程度上作為組件的文檔,而且如果其他開發者在使用你的組件時傳遞了錯誤的類型,也會在瀏覽器控制臺中拋出警告。

          傳遞 prop 的細節

          Prop 屬性命名

          如果一個 prop 的名字很長,應使用 camelCase 形式,因為它們是合法的 JavaScript 標識符

          defineProps({
            greetingMessage: String
          })
          
          <span>{{ greetingMessage }}</span>
          
          //推薦寫法
          <MyComponent greeting-message="hello" />
          //或者
          <MyComponent greetingMessage="hello" />
          
          

          模版上使用屬性則通常會將其寫為 kebab-case 形式,這樣和 HTML attribute 寫法就一致了。

          靜態 vs. 動態 Prop

          簡單講 就是傳入數值是字符串還是變量

          //這是靜態
          <Com14 person="王大可" />
          //這是動態
          <Com14 :person="personName" />
          

          使用一個對象綁定多個 prop

          v-bind 直接綁定對象,即只使用 v-bind 而非某一個屬性

          const post={
          id: 1,
          title: 'My Journey with Vue'
          }
          
          <BlogPost v-bind="post" />
          // 實際等價于
          <BlogPost :id="post.id" :title="post.title" />
          

          單向數據流

          1. 所有的 props 都遵循著單向綁定原則,props 因父組件的更新而變化,自然地將新的狀態向下流往子組件,而不會逆向傳遞。
          2. 這避免了子組件意外修改父組件的狀態的情況,不然應用的數據流將很容易變得混亂而難以理解。
          3. 每次父組件更新后,所有的子組件中的 props 都會被更新到最新值,這意味著你不應該在子組件中去更改一個 prop。若你這么做了,Vue 會在控制臺上向你拋出警告:
          const props=defineProps(['foo'])
          
          // ? 警告!prop 是只讀的!
          props.foo='bar'
          

          「更改 props 的場景:」

          prop 被用于傳入初始值;而子組件想在之后將其作為一個局部數據屬性。

          在這種情況下,最好是新定義一個局部數據屬性,從 props 上獲取初始值即可

          const props=defineProps(['initialCounter'])
          
          // 計數器只是將 props.initialCounter 作為初始值
          // 像下面這樣做就使 prop 和后續更新無關了
          const counter=ref(props.initialCounter)
          

          需要對傳入的 prop 值做進一步的轉換。

          在這種情況中,最好是基于該 prop 值定義一個計算屬性:

          const props=defineProps(['size'])
          
          // 該 prop 變更時計算屬性也會自動更新
          const normalizedSize=computed(()=> props.size.trim().toLowerCase())
          

          Prop 校驗

          1. Vue 組件可以更細致地聲明對傳入的 props 的校驗要求。
          2. 比如我們上面已經看到過的類型聲明,如果傳入的值不滿足類型要求,Vue 會在瀏覽器控制臺中拋出警告來提醒使用者。
          defineProps({
            // 基礎類型檢查
            // (給出 `null` 和 `undefined` 值則會跳過任何類型檢查)
            propA: Number,
            // 多種可能的類型
            propB: [String, Number],
            // 必傳,且為 String 類型
            propC: {
              type: String,
              required: true
            },
            // Number 類型的默認值
            propD: {
              type: Number,
              default: 100
            },
            // 對象類型的默認值
            propE: {
              type: Object,
              // 對象或數組的默認值
              // 必須從一個工廠函數返回。
              // 該函數接收組件所接收到的原始 prop 作為參數。
              default(rawProps) {
                return { message: 'hello' }
              }
            },
            // 自定義類型校驗函數
            // 在 3.4+ 中完整的 props 作為第二個參數傳入
            propF: {
              validator(value, props) {
                // The value must match one of these strings
                return ['success', 'warning', 'danger'].includes(value)
              }
            },
            // 函數類型的默認值
            propG: {
              type: Function,
              // 不像對象或數組的默認,這不是一個
              // 工廠函數。這會是一個用來作為默認值的函數
              default() {
                return 'Default function'
              }
            }
          })
          
          

          defineProps() 宏中的參數不可以訪問 <script setup> 中定義的其他變量,因為在編譯時整個表達式都會被移到外部的函數中。

          額外說明:

          • 所有 prop 默認都是可選的,除非聲明了 required: true
          • 除 Boolean 外的未傳遞的可選 prop 將會有一個默認值 undefined。
          • Boolean 類型的未傳遞 prop 將被轉換為 false。這可以通過為它設置 default 來更改——例如:設置為 default: undefined 將與非布爾類型的 prop 的行為保持一致。
          • 如果聲明了 default 值,那么在 prop 的值被解析為 undefined 時,無論 prop 是未被傳遞還是顯式指明的 undefined,都會改為 default 值。

          當 prop 的校驗失敗后,Vue 會拋出一個控制臺警告 (在開發模式下)。

          運行時類型檢查

          校驗選項中的 type 可以是下列這些原生構造函數:

          • String
          • Number
          • Boolean
          • Array
          • Object
          • Date
          • Function
          • Symbol

          type 也可以是自定義的類或構造函數,Vue 將會通過 instanceof 來檢查類型是否匹配。

          class Person {
            constructor(firstName, lastName) {
              this.firstName=firstName
              this.lastName=lastName
            }
          }
          
          defineProps({
            author: Person
          })
          
          

          Vue 會通過 instanceof Person 來校驗 author prop 的值是否是 Person 類的一個實例。

          Boolean 類型轉換

          1. 組件屬性使用 Boolean 類型
          defineProps({
            disabled: Boolean
          })
          
          <!-- 等同于傳入 :disabled="true" -->
          <MyComponent disabled />
          
          <!-- 等同于傳入 :disabled="false" -->
          <MyComponent />
          
          1. prop 被聲明為允許多種類型時

          只有當 Boolean 出現在 String 之前時,Boolean 轉換規則才適用

          一節講到對于元素的操作和瀏覽器的常用操作如何通過代碼實現,這次來學習如何通過定位元素,來獲取元素的信息(元素屬性、信息等)

          獲取元素相關的信息

          size:元素的大小

          text:元素內文本

          is_displayed( ) :元素是否可見

          is_enabled(): 元素是否可用(一般用于判斷按鈕是否置灰)

          is_selected( ) : 元素是否被選中(一般用于表單中的單選框和復選框)

          get_attribute ( ) : 元素的屬性(可以獲取到所選標簽內的屬性信息)


          通過如圖所示選中的元素來演示如何獲取元素的屬性

          from selenium import webdriver
           
          driver=webdriver.Chrome()
          driver.get("http://news.baidu.com/")
           
          # 新聞標題
          element1=driver.find_element_by_css_selector("label[class='not-checked']")
          # 新聞標題選擇框
          element2=driver.find_element_by_css_selector("#newstitle")
           
          # 新聞標題的大?。▄'height', 'width'})
          print(element1.size)
           
          # 新聞標題的文本
          print(element1.text)
           
          # 新聞標題是否可見
          print(element1.is_displayed())
           
          # 新聞標題標簽內的for屬性
          print(element1.get_attribute("for"))
           
          # 新聞標題選擇框是否被選中
          print(element2.is_selected())

          結果:


          主站蜘蛛池模板: 日韩美一区二区三区| 一区二区三区波多野结衣| 国产婷婷色一区二区三区| 91久久精品无码一区二区毛片| 国产伦精品一区二区三区精品 | 亚洲第一区在线观看| 人妻AV中文字幕一区二区三区| 色一乱一伦一区一直爽| 久久精品成人一区二区三区| 亚洲美女视频一区| 中文字幕精品一区二区日本| 无码人妻一区二区三区av| 波多野结衣一区视频在线| 日韩免费无码一区二区三区 | 中日av乱码一区二区三区乱码| 性色AV一区二区三区天美传媒| 亚洲AⅤ无码一区二区三区在线| 中文字幕av无码一区二区三区电影| 日韩精品无码久久一区二区三| 在线观看日韩一区| 国产一区二区三区在线电影| 久久se精品动漫一区二区三区| 亚洲欧洲无码一区二区三区| 日本无卡码一区二区三区| 日韩人妻不卡一区二区三区 | 日韩一区在线视频| 国产免费伦精品一区二区三区| 亚洲蜜芽在线精品一区| 色综合视频一区二区三区| 久久精品无码一区二区无码| 一区二区三区四区电影视频在线观看| 一区二区三区日韩精品| 无码人妻精品一区二区蜜桃百度| 3d动漫精品成人一区二区三| 日韩视频在线观看一区二区| 无码国产精品一区二区免费虚拟VR| 亲子乱AV视频一区二区| 精品国产天堂综合一区在线| 色窝窝无码一区二区三区 | а天堂中文最新一区二区三区| 中文无码一区二区不卡αv|