Ng-Matero 0.3 已發佈,新增 module schematic 以及 page schematic,詳見 READMEhtml
Angular Material 做爲 Angular 的官方組件庫,不管是設計交互仍是易用性都有着極高的質量。正如官方所說其目的就是構建基於 Angular 和 TypeScript 的高質量組件庫。前端
官方列舉了以下幾點來解釋「高質量」的含義。git
- 國際化和可訪問性,以便全部用戶均可以使用。
- 不會讓開發人員感到困惑的簡單 API。
- 在各類各樣沒有 bug 的用例中按預期行事。
- 經過單元測試和集成測試更好地測試行爲。
- 可在 Material Design 規範的範圍內進行定製。
- 將性能開銷降至最低。
- 代碼簡潔,文檔友好,能夠做爲 Angular 開發人員的一個例子。
Material Design 做爲一個很是流行的設計語言,它有多個版本的實現。React 版的 Material Design 有着很高的人氣,你們能夠自行對比,我就不贅述了,以避免引發無謂的爭吵,進而扯到框架層面。我能夠說一下本身的感覺,Angular Material 的交互更加流暢,細節作的更好。github
Angular Material 組件庫雖然很優秀,可是卻被戴上了只適合作 C 端界面的帽子。這也是我剛開始不敢選擇 Angular Material 的一個緣由。可是在編寫 ng-matero 的過程當中,隨着對 Angular Material 的深刻了解,我發現這種說法稍顯狹隘甚至產生了必定的誤導,因此我但願這篇文章可讓你們對 Angular Material 有一個更加正確的認識。接下來我會從相對宏觀的角度介紹 Angular Material 設計的一些亮點,而且簡單介紹 Angular Material 的一些使用技巧。swift
題外話:爲何 ng-matero 會選擇 Angular Material?sass
拋開官方提到的幾點不談。首先我是那種比較激進的開發者,對於先進的設計理念,我都有躍躍欲試的執念。國內的 Element UI 以及 Ant Design 都是 Bootstrap 3 時代的風格。隨着業務人員對界面細緻緊湊的要求愈來愈高,我發現 Material 的設計風格更加符合需求,層次感更強。不過最主要的仍是 Material Design 的交互更吸引我。另外,Angular Material 的樣式是基於 Sass 編寫,而我最喜歡的也是 Sass,因此基於 Angular Material 編寫 ng-matero 就是宿命的選擇。順便插一句,若是你們糾結用 Sass 仍是 Less,能夠看一下這篇文章 CSS 預處理器中的循環,我的不建議用 Less,請原諒我無心引戰🤪。antd
Less is more(少便是多)—— 密斯·凡德羅app
我想不少人對 Angular Material 望而卻步的緣由之一就是它的組件看上去有點少。然而在通常的業務中這些組件已經夠用。除了經常使用組件以外,Angular Material 還有一個組件開發包 CDK。在設計界有一句名言「少便是多」,蘋果的產品就是最好的證實。把這句名言用在 Angular Material 上絲絕不爲過,其實除了咱們看到的組件以外,Material 還有一些隱藏組件,好比能夠用 menu
組件構造 popover
,我會在下文中介紹。框架
Material Design 的亮點之一就是擁有很是豐富的顏色值,其實 Angular Material 的顏色變量比官方定義的色值還要多一些。你們能夠點擊 ng-matero 的 colors 頁面 查看。ng-matero 也有全部顏色值對應的 colors helper,能夠更加方便的建立豐富多彩的按鈕或標籤。Angular Material 的顏色定義嚴謹且優雅。如下是紅色值的變量。tcp
$mat-red: (
50: #ffebee,
100: #ffcdd2,
200: #ef9a9a,
300: #e57373,
400: #ef5350,
500: #f44336,
600: #e53935,
700: #d32f2f,
800: #c62828,
900: #b71c1c,
A100: #ff8a80,
A200: #ff5252,
A400: #ff1744,
A700: #d50000,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $light-primary-text,
A400: $light-primary-text,
A700: $light-primary-text,
)
);
複製代碼
除了定義基礎色值以外,還有相對應的文本色定義,很是嚴謹。我在之前寫 helper 庫 的時候,曾寫過顏色集羣,文本色處理都是一刀切,很是不嚴謹,因此感觸很是深。更驚喜的的是 Angular Material 甚至給出了灰色值的別名。
// Alias for alternate spelling.
$mat-gray: $mat-grey;
複製代碼
Angular Material 的樣式幾乎所有寫在了 mixin
中,定製起來很是容易。我最開始認爲將全部樣式所有寫到 mixin
中並非很優雅的作法,可是在編寫 ng-matero 暗黑主題的時候,我發現不這樣作是不行的。如下是 Angular Material 主題定製的方法。
@import '~@angular/material/theming';
// Include non-theme styles for core.
@include mat-core();
// Define a theme.
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);
// Include all theme styles for the components.
@include angular-material-theme($candy-app-theme);
複製代碼
Angular Material 給出了多套主題的設置方法,只須要增長樣式控制類就能夠了。
// Define an alternate dark theme.
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
$dark-warn: mat-palette($mat-deep-orange);
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
// `.unicorn-dark-theme` will be affected by this alternate dark theme instead of the default theme.
.unicorn-dark-theme {
@include angular-material-theme($dark-theme);
}
複製代碼
在此我簡單介紹一下 ng-matero 的主題切換。增長樣式控制類能夠說是最簡單的主題切換方式,可是缺點就是同時擁有多套主題,代碼量太大。若是隻做爲 DEMO 展現是沒問題的,可是生產環境不推薦這樣作。
ng-matero 在使用 ng add
初始化的時候增長了預構建主題選項,生成的主題只有一份,若是有特殊需求能夠自行定製。實現方式就是不一樣主題傳入不一樣變量,可是這種狀況下多主題控制會有問題。因此必須使用 mixin 編寫某些樣式,這樣的話就能夠有局部變量環境。以下:
.theme-dark {
$primary: mat-palette($mat-pink, 700, 500, 900);
$accent: mat-palette($mat-blue-grey, A200, A100, A400);
$warn: mat-palette($mat-red);
$theme: mat-dark-theme($primary, $accent, $warn);
@include angular-material-theme($theme);
@include matero-admin-theme($theme);
}
複製代碼
Angular Material 提供了幾乎全部和 Material Design 有關的樣式工具,包括變量
、 function
和 mixin
,均可以在 theming 文件中找到。
除了上面提到的主題定製 function
、mixin
以外,咱們還可使用 mat-elevation()
輕鬆製做 MD 陰影。另外咱們還可使用 $swift-ease-out-timing-function
、$mat-fast-out-slow-in-timing-function
這些動畫變量實現和 MD 同樣的動畫效果。
基於這套工具集,咱們能夠很容易的搭建和 MD 風格相統一的界面。
Angular Material 的官方文檔可能稍微不太友好,總感受內容不少,看不進去。可是耐心看一下,就會發現其簡潔之道,Angular Material 的 API 也是「少便是多」的一種表現。以表單組件爲例,如下是一個滑塊組件。
<mat-slide-toggle [(ngModel)]="options.model" (change)="changeOptions()" [disabled]="options.disabled">visible
</mat-slide-toggle>
複製代碼
Angular Material 的表單組件更像是對原生 html 元素的複寫。在熟悉了一種組件以後,幾乎不須要額外的記憶成本,就能夠很容易的猜到某些 API,簡單易懂,使用很方便。不過期常翻文檔仍是頗有必要的。
再看一下菜單組件,使用方式一樣很是簡單。
<button mat-button [matMenuTriggerFor]="menu">Menu</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
複製代碼
在我更新 ng-zorro-antd 8.x 以後,我發現 zorro 的菜單組件的使用已經和 Angular Material 同樣了。可見優秀的設計理念會被普遍借鑑。
Angular Material 的菜單組件能夠說很是強大,除了官網提到的功能以外,咱們還能夠用如下方式實現動態數據加載的多級菜單,好比 ng-matero 的 Top Menu 佈局。
<a mat-button [routerLink]="['/', menuItem.state]" *ngIf="menuItem.type === 'link'">
<span>{{menuItem.name}}</span>
...
</a>
...
<!-- level 1 -->
<button mat-button *ngIf="menuItem.type === 'sub'" [matMenuTriggerFor]="menulevel1">
<span>{{menuItem.name}}</span>
...
</button>
<mat-menu #menulevel1="matMenu">
<ng-container *ngFor="let childLvl1 of menuItem.children">
<a mat-menu-item [routerLink]="['/', menuItem.state, childLvl1.state]" *ngIf="childLvl1.type === 'link'">{{childLvl1.name}}</a>
...
<!-- level 2 -->
<button mat-menu-item *ngIf="childLvl1.type === 'sub'" [matMenuTriggerFor]="menulevel2">{{ childLvl1.name }}</button>
<mat-menu #menulevel2="matMenu">
<ng-container *ngFor="let childLvl2 of childLvl1.children">
<a mat-menu-item [routerLink]="filterStates(['/', menuItem.state, childLvl1.state, childLvl2.state])" *ngIf="childLvl2.type === 'link'">{{childLvl2.name}}</a>
...
</ng-container>
</mat-menu>
</ng-container>
</mat-menu>
複製代碼
另外,菜單組件還能夠實現 popover
的效果,不過須要作一些特殊處理,以下:
<mat-menu class="menu-form-wrapper" [hasBackdrop]="false">
<div (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
...
</div>
</mat-menu>
複製代碼
最後能夠根據本身的需求調整一下樣式。
Angular Material 的表格是我見過最特殊的表格,結構簡潔,經過定義動態列渲染數據,如下是一個官網例子:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order. The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
複製代碼
相比於 ng-zorro-antd 會暴露所有的 DOM 結構,這種簡潔的結構(CDKTable
的結構也是如此)確實讓人不適應,甚至有一些擔心,遇到複雜的需求會不會吃癟。在我寫了大量表格需求以後,我能夠很確定地說 Angular Material 的表格足以應對複雜需求(話也不敢說太滿😅)。
我很贊同 ng-alain 對 ng-zorro-antd 表格的進一步抽象,熟悉了 ng-alain 編寫表格的方式以後,我一直覺得 mat-table
略顯笨拙。然而仔細研究一下就會發現,mat-table
是在 DOM 層面的抽象,本質是同樣的。
mat-table
對錶格列寬的首選操控方式是 CSS,起初我對這種方式也存在疑慮,可是在我親自封裝了 ng-zorro-antd 的表格組件以後,我發現一切都很天然。這讓我想起前端流行的一句話,「凡事能用 CSS 完成的就不要用 JS」,這也是我不建議你們用 Less 的緣由之一。
ng-matero 的表格示例是最簡單的業務表格,能夠參考其實現方法。
Angular Material 並無佈局組件。可是不用擔憂,官方出品了一款基於指令佈局的神器 flex-layout,它是專門爲 Angular 設計的。基於指令的佈局方式和 Bootstrap 的柵格佈局是兩種不一樣的設計理念。flex-layout 的使用很簡單,能夠很快上手,熟悉以後你必定會喜歡這種佈局方式。
文章篇幅有限,以我淺薄的資歷還沒法將 Angular Material 的設計之美剖析的面面俱到,可是若是你們經過這篇文章可以更好的瞭解 Angular Material 或者對 Angular Material 產生了一點興趣,我也算是作了一件好事。
任何組件庫都沒法知足全部業務需求,若是你沒法在 Angular Material 中找到可用的組件,你能夠嘗試第三方組件,或者能夠將 ng-zorro-antd 按模塊單獨引入。在此推薦一些優秀的第三方組件。
若是你們喜歡 Angular 或者對 Angular Material 感興趣,歡迎進羣討論!