angular6的table組件開發(fā)的實(shí)現(xiàn)示例
背景及吐槽:
今年有機(jī)會(huì)再次接觸angualr這個(gè)框架,想起第一次接觸ng還是16年讀書的時(shí)候,當(dāng)時(shí)還是ng1,然后學(xué)起來(lái)特別辛苦,學(xué)習(xí)曲線特別陡峭;而今年有一個(gè)項(xiàng)目重構(gòu)直接采用了angular6,而后面該項(xiàng)目后面由我負(fù)責(zé)開發(fā)和維護(hù),然后我又重新再學(xué)習(xí)了ng6,本以為有ng1的基礎(chǔ),學(xué)起來(lái)會(huì)好一些,然并卵,學(xué)習(xí)的曲線特別陡峭,但還是最后將ng6啃下來(lái)(很不情愿去學(xué)的,但沒辦法)?;貧w到項(xiàng)目,該項(xiàng)目沒有引入其他組件庫(kù),所以很多基礎(chǔ)組件都是自己開發(fā)(用ng開發(fā)那種酸爽很帶勁),其中table組件讓我思考了差不多兩個(gè)星期,最后才開發(fā)出來(lái),吐槽完畢,接下來(lái)就介紹一下我的做法,我的做法不一定最正確。
形式:
主要參考element里面的table組的格式:
vue:
<el-table :data="tableData">
<el-table-column prop="date" label="日期"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
</template>
</el-table-column>
</el-table>
所以得到了angualr的table組件的格式:
<app-widget-table [data]="tableData">
<app-widget-table-column prop="date" label="日期"></app-widget-table-column>
<app-widget-table-column label="操作">
<ng-template #scope let-row="scope">
<ng-widget-button (click)="handleClick(row)" type="text" size="small">查看</el-button>
</ng-template>
</app-widget-table-column>
</app-widget-table>
在angular的table組件中,最為困難就是ng-template如何將作用域綁定到ng-widget-button組件中;
關(guān)鍵點(diǎn)知識(shí)講解:
ng-content:
可以將父組件中所包含的所有子組件,都插入table組件中ng-container所在的位置,跟vue中的slot很像;
ng-container:
可以作為一個(gè)組件的模板,跟vue里面的template組件很像;
ng-template:
該東西,是整個(gè)組件中最為麻煩的一個(gè)東西,直接使用它,會(huì)沒有任何效果,必須要和TemplateRef和ngTemplateOutlet一起使用,才有有效果,主要是作為模板并引入作用域,具體原理可以看一下官方文檔(https://www.angular.cn/api)
TemplateRef:
主要是用來(lái)獲取ng-template組件的引用;
ngTemplateOutlet:
將ng-template的內(nèi)容在html頁(yè)面展示出來(lái),并綁定變量,就像vue中的router-view;
QueryList:
獲取table組件中所有的內(nèi)容指引;
ContentChildren:
內(nèi)容映射的接口,針對(duì)多個(gè)子元素采用
ContentChild:
內(nèi)容映射的接口,針對(duì)單個(gè)子元素采用
先對(duì)app-widget-table-column組件進(jìn)行分析:
該組件的作用就是為了運(yùn)輸數(shù)據(jù),并且引入內(nèi)容,該組件本身是不會(huì)有任何操作和邏輯,就是一個(gè)運(yùn)輸工;
table-column.component.html:
<ng-container></ng-container>
table-column.component.ts:
import {Component, Input, Output, TemplateRef, ContentChild, AfterContentInit} from '@angular/core';
@Component({
selector: 'app-widget-table-column',
templateUrl: './table-column.component.html',
styleUrls: ['./table-column.component.less'],
preserveWhitespaces: false
})
export class TableColumnComponent implements AfterContentInit {
constructor() {
}
@Input()
label: string;
@Input()
prop: string;
@Input()
class: string;
@Input()
style: object;
@ContentChild('scope') // 獲取ng-template組件的一個(gè)本地變量,并修飾scope對(duì)象
scope: TemplateRef<any>; // 獲取ng-template的指引,主要是其內(nèi)容,any表示該指可以是任何內(nèi)容
ngAfterContentInit(): void {}
}
table.component.html
<div>
<div>
<ng-content></ng-content> // 主要是用來(lái)引入整個(gè)table組件的內(nèi)容,但不會(huì)在頁(yè)面顯示任何內(nèi)容
</div>
<table class="table">
<thead>
<tr>
<th *ngFor="let label of labelList">{{label}}</th> // 類似于v-for,主要講table-cloumn的所有l(wèi)abel搜集,并展示
</tr>
</thead>
<tbody *ngIf="data.length > 0">
<ng-container *ngFor="let item of data; let i = index">
<tr>
<ng-container *ngFor="let row of tableColumn['_results']">
<td *ngIf="row.prop" [ngStyle]="row.style" [ngClass]="row.class">{{item[row.prop]}}</td> // 直接展示
<td *ngIf="row.scope" [ngStyle]="row.style" [ngClass]="row.class">
<ng-container *ngTemplateOutlet="row.scope; context: {$implicit: {}, scope: data[i]}">
</ng-container> // 展示ng-template的內(nèi)容
</td>
</ng-container>
</tr>
</ng-container>
</tbody>
</table>
<div *ngIf="data.length === 0" class="none-data">暫無(wú)數(shù)據(jù)!</div>
</div>
table.component.ts:
import {Component, OnInit, Input, Output, ContentChildren, AfterContentInit, ViewChild, AfterViewInit, QueryList} from '@angular/core';
import {TableColumnComponent} from '../table-column/table-column.component';
@Component({
selector: 'app-widget-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.less'],
preserveWhitespaces: false
})
export class TableComponent implements OnInit, AfterContentInit {
constructor() {
}
@ContentChildren(TableColumnComponent)
tableColumn: QueryList<TableColumnComponent>; // 獲取table-cloumn組件的所有實(shí)例
@Input()
data: object[];
labelList: string[] = [];
ngOnInit(): void {
if (!(this.data instanceof Array)) {
throw new Error('the data into TableComonent must be Array!');
}
}
ngAfterContentInit(): void {
this.labelList = this.tableColumn['_results'].map(item => item.label);
}
}
雖然看起來(lái)這兩個(gè)組件的代碼不多,但里面的邏輯卻比較繞,這也證明了ng用起來(lái)十分難上手,不過(guò)真的稱贊的是,ng采用ts和rx,用上手確實(shí)是比較爽。
這兩個(gè)組件目前還是比較粗糙,功能和特性也不是特別多,只能滿足一般表格的需求,后續(xù)會(huì)繼續(xù)完善該組件以及其他項(xiàng)目中用ng來(lái)開發(fā)的基礎(chǔ)組件,希望能沉淀出一套ng的組件庫(kù)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
angular實(shí)現(xiàn)頁(yè)面打印局部功能的思考與方法
這篇文章主要給大家介紹了關(guān)于angular實(shí)現(xiàn)頁(yè)面打印局部功能的思考與方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04
解決angularjs中同步執(zhí)行http請(qǐng)求的方法
今天小編就為大家分享一篇解決angularjs中同步執(zhí)行http請(qǐng)求的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
angular實(shí)現(xiàn)form驗(yàn)證實(shí)例代碼
本篇文章主要介紹了angular實(shí)現(xiàn)form驗(yàn)證實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
AngularJS中過(guò)濾器的使用與自定義實(shí)例代碼
這篇文章運(yùn)用實(shí)例代碼給大家介紹了angularjs中過(guò)濾器的使用和自定義過(guò)濾器,對(duì)大家學(xué)習(xí)AngularJS具有一定的參考借鑒價(jià)值,感興趣的朋友們可以參考借鑒。2016-09-09
AngularJS ng-bind-html 指令詳解及實(shí)例代碼
本文主要是對(duì)AngularJS ng-bind-html 指令知識(shí)的詳細(xì)講解,并附代碼實(shí)例,有需要的小伙伴可以參考下2016-07-07
ng-events類似ionic中Events的angular全局事件
這篇文章主要介紹了ng-events類似ionic中Events的angular全局事件,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
Angularjs 實(shí)現(xiàn)移動(dòng)端在線測(cè)評(píng)效果(推薦)
這篇文章主要介紹了Angularjs 實(shí)現(xiàn)移動(dòng)端在線測(cè)評(píng)效果,需要的朋友可以參考下2017-04-04
Angularjs過(guò)濾器實(shí)現(xiàn)動(dòng)態(tài)搜索與排序功能示例
這篇文章主要介紹了Angularjs過(guò)濾器實(shí)現(xiàn)動(dòng)態(tài)搜索與排序功能,涉及AngularJS過(guò)濾器相關(guān)搜索、查詢、排序操作技巧,需要的朋友可以參考下2017-12-12
AngularJS中實(shí)現(xiàn)動(dòng)畫效果的方法
本文主要介紹AngularJS 動(dòng)畫,這里對(duì)動(dòng)畫的資料詳細(xì)介紹并附有效果圖和代碼實(shí)例,有需要的小伙伴參考下2016-07-07

