angular6的table組件開發(fā)的實現(xiàn)示例
背景及吐槽:
今年有機(jī)會再次接觸angualr這個框架,想起第一次接觸ng還是16年讀書的時候,當(dāng)時還是ng1,然后學(xué)起來特別辛苦,學(xué)習(xí)曲線特別陡峭;而今年有一個項目重構(gòu)直接采用了angular6,而后面該項目后面由我負(fù)責(zé)開發(fā)和維護(hù),然后我又重新再學(xué)習(xí)了ng6,本以為有ng1的基礎(chǔ),學(xué)起來會好一些,然并卵,學(xué)習(xí)的曲線特別陡峭,但還是最后將ng6啃下來(很不情愿去學(xué)的,但沒辦法)。回歸到項目,該項目沒有引入其他組件庫,所以很多基礎(chǔ)組件都是自己開發(fā)(用ng開發(fā)那種酸爽很帶勁),其中table組件讓我思考了差不多兩個星期,最后才開發(fā)出來,吐槽完畢,接下來就介紹一下我的做法,我的做法不一定最正確。
形式:
主要參考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)鍵點知識講解:
ng-content:
可以將父組件中所包含的所有子組件,都插入table組件中ng-container所在的位置,跟vue中的slot很像;
ng-container:
可以作為一個組件的模板,跟vue里面的template組件很像;
ng-template:
該東西,是整個組件中最為麻煩的一個東西,直接使用它,會沒有任何效果,必須要和TemplateRef和ngTemplateOutlet一起使用,才有有效果,主要是作為模板并引入作用域,具體原理可以看一下官方文檔(https://www.angular.cn/api)
TemplateRef:
主要是用來獲取ng-template組件的引用;
ngTemplateOutlet:
將ng-template的內(nèi)容在html頁面展示出來,并綁定變量,就像vue中的router-view;
QueryList:
獲取table組件中所有的內(nèi)容指引;
ContentChildren:
內(nèi)容映射的接口,針對多個子元素采用
ContentChild:
內(nèi)容映射的接口,針對單個子元素采用
先對app-widget-table-column組件進(jìn)行分析:
該組件的作用就是為了運輸數(shù)據(jù),并且引入內(nèi)容,該組件本身是不會有任何操作和邏輯,就是一個運輸工;
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組件的一個本地變量,并修飾scope對象 scope: TemplateRef<any>; // 獲取ng-template的指引,主要是其內(nèi)容,any表示該指可以是任何內(nèi)容 ngAfterContentInit(): void {} }
table.component.html
<div> <div> <ng-content></ng-content> // 主要是用來引入整個table組件的內(nèi)容,但不會在頁面顯示任何內(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">暫無數(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組件的所有實例 @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); } }
雖然看起來這兩個組件的代碼不多,但里面的邏輯卻比較繞,這也證明了ng用起來十分難上手,不過真的稱贊的是,ng采用ts和rx,用上手確實是比較爽。
這兩個組件目前還是比較粗糙,功能和特性也不是特別多,只能滿足一般表格的需求,后續(xù)會繼續(xù)完善該組件以及其他項目中用ng來開發(fā)的基礎(chǔ)組件,希望能沉淀出一套ng的組件庫。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解AngularJS中$http緩存以及處理多個$http請求的方法
$http 是 AngularJS 中的一個核心服務(wù),用于讀取遠(yuǎn)程服務(wù)器的數(shù)據(jù),通過本文給大家介紹AngularJS中$http緩存以及處理多個$http請求的方法,希望的朋友一起學(xué)習(xí)吧2016-02-02體驗jQuery和AngularJS的不同點及AngularJS的迷人之處
AngualrJS是一個很貼心的web應(yīng)用框架,本篇通過jQuery和Angular兩種方式來實現(xiàn)同一個實例,從而體驗兩者的不同點以及AngularJS的迷人之處2016-02-02解決angular2在雙向數(shù)據(jù)綁定時[(ngModel)]無法使用的問題
今天小編就為大家分享一篇解決angular2在雙向數(shù)據(jù)綁定時[(ngModel)]無法使用的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09angular中的http攔截器Interceptors的實現(xiàn)
本篇文章主要介紹了angular中的http攔截器Interceptors的實現(xiàn)的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02