【Angular】@Input和@Output
阿新 • • 發佈:2019-02-01
【@Input和@Output】
@Input和@Output這兩個要結合父元件與子元件來說
- @Input:是屬相繫結,父元件向子元件傳遞資料
- @Output:是事件繫結,子元件向父元件傳遞資料的同時觸發事件
【舉例說明】
testtable是父元件,datatable是子元件
主要功能:table實現分頁顯示,點選刪除按鈕時刪除資料。為了更好的解耦,比如當頁數改變或標題改變時,不去改動主要實現程式碼,只需改變父元件的頁數或標題即可,就滿足了需求的改變。
//testtable.component.ts
export class TesttableComponent implements OnInit {
values = ["","#","First Name","Last Name","User Name","操作"];
attributeValues = ["id","FirstName","LastName","UserName"];
Users=[
{ id: 1, FirstName: 'wang',LastName:'shuang',UserName:'1' },
{ id: 2, FirstName: 'li',LastName:'hua',UserName:'2' },
{ id: 3, FirstName: 'zhao' ,LastName:'nan',UserName:'3'},
{ id: 4, FirstName: 'niu',LastName:'qian',UserName:'4' },
{ id: 5, FirstName: 'yan',LastName:'wen',UserName:'5' },
{ id: 6, FirstName: 'liu',LastName:'wen',UserName:'6' },
{ id: 7, FirstName: 'bai',LastName:'jing',UserName:'7' },
{ id: 8, FirstName: 'an' ,LastName:'jing',UserName:'8'},
{ id: 9, FirstName: 'wei',LastName:'yuan',UserName:'9' },
{ id: 10, FirstName: 'kou',LastName:'ru',UserName:'10' },
];
//頁號
page:number;
//總記錄數
total:number;
//頁的大小
pageSize:number;
//總頁數
totalPages:number;
constructor() { }
ngOnInit() {
this.page=1;
this.pageSize=4;
this.total=this.Users.length;
this.totalPages=this.total/this.pageSize;
}
//el:選中的索引
doRealDelete(el:any){
for(let i=0;i<el.length;i++){
this.Users.splice(el[i]-i,1);
}
}
}
【註釋】
- 為什麼要在ngOnInit()中賦值:查了查Angular的官網是這樣說的: 在Angular第一次顯示資料繫結和設定指令/元件的輸入屬性之後,初始化指令/元件,在第一輪ngOnChanges()完成之後呼叫,只調用一次。我就簡單粗暴的這樣記了:用於初始化。所以賦值寫在了ngOnInit()中。如果在全域性變數中將一個表示式的值賦值給變數時很可能會出錯
- this.Users.splice(el[i]-i,1):el是子元件傳過來的選中行的索引值,但在每次刪除時User的數量就會減一,及所以就會減一,如果還按原來的索引減,就不行了,要在原來的索引上都先去已刪除的個數,這樣索引就變為刪除之後的索引了,這樣刪除成功
//testtable.component.html
<app-datatable [titles]="values" [attribute]="attributeValues" [users]="Users" [page]="page" [pageSize]=pageSize [total]=total [totalPages]=totalPages (doDelete)="doRealDelete($event)">
</app-datatable>
【註釋】
<app-datatable>
是子元件的選擇器- 通過[變數]向子元件傳遞資料
- [titles]=”values”:valuse是父元件中的一個變數,複製給titles,然後在子元件中用@Input() titles來接收傳過來的值,名稱必須一致
- (doDelete)是子元件傳過來的觸發事件,名稱必須一致,(doDelete)事件又由doRealDelete()來觸發
//testtable.module.ts
import { DatatableComponent } from '../datatable/datatable.component'; //匯入子元件
@NgModule({
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(TesttableRoutes)
],
declarations: [TesttableComponent,DatatableComponent]
})
export class TesttableModule { }
【註釋】
- 必須在父元件中匯入子元件
//datatable.component.ts 在上一篇上新增如下內容
export class DatatableComponent implements OnInit {
@Input() titles;
@Input() attribute;
@Input() users:string[][]=new Array();
@Input() page:number;
@Input() total:number;
@Input() pageSize:number;
@Input() totalPages:number;
@Output() doDelete= new EventEmitter<any>();
checked=new Array<boolean>();//是否被選中
constructor() {}
ngOnInit() {
}
//選中行
select(i:number,ckbox:HTMLInputElement){
this.checked[i] = ckbox.checked;
}
//刪除選中行
deleteDatas(){
let isDelete = false;
//let ids = new Array<string>(); //存放選中的索引
let dataCount = new Array();
for (let j=0;j<this.checked.length;j++){
if(this.checked[j]){
dataCount.push(j); //選中的索引
isDelete = true; //標識有無選中的
}
}
if(!isDelete){
alert("請至少選中一條記錄");
return;
}
this.doDelete.emit(dataCount);//給父元件選中的索引
}
//初始化,設為初始態都為false,未選中
disposeChecked(){
this.checked.length = this.users.length;
for (let i = 0; i < this.users.length; i++) {
this.checked[i] = false;
}
}
}
【註釋】
- Math.ceil():是個向上取整函式當,此處必須有,否則會出現類似2.5頁的情況
- @Output() doDelete= new EventEmitter(); 建立一個事件源,當執行deleteDatas()就會觸發該事件源,然後讓父元件執行此方法
- @Input() 來接受父元件傳過來的值
<!--在上 一篇部落格的基礎上,在html上新增一個刪除按鈕 -->
<div>
<button (click)="deleteDatas()">刪除</button>
</div>
@NgModule({
imports: [
CommonModule,
FormsModule
],
declarations: [DatatableComponent],
exports:[DatatableComponent] //匯出元件
})
【註釋】
要想別人用你的元件,必須將自己的元件匯出 exports:[DatatableComponent]
結果展示: