该篇是上一篇的改编:【Angular】table假分页
【@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',UserName:'6' },{ id: 7,FirstName: 'bai',LastName:'jing',UserName:'7' },{ id: 8,FirstName: 'an',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() 来接受父组件传过来的值
- @NgModule({
- imports: [
- CommonModule,FormsModule
- ],declarations: [DatatableComponent],exports:[DatatableComponent] //导出组件
- })
【注释】
要想别人用你的组件,必须将自己的组件导出 exports:[DatatableComponent]
结果展示: