Angular Material 的设计之美

前言

Angular Material 作为 Angular 的官方组件库,无论是设计交互还是易用性都有着极高的质量。正如官方所说其目的就是构建基于 Angular 和 TypeScript 的高质量组件库。

官方列举了如下几点来解释“高质量”的含义。

  • 国际化和可访问性,以便所有用户都可以使用。
  • 不会让开发人员感到困惑的简单 API。
  • 在各种各样没有 bug 的用例中按预期行事。
  • 通过单元测试和集成测试更好地测试行为。
  • 可在 Material Design 规范的范围内进行定制。
  • 将性能开销降至最低。
  • 代码简洁,文档友好,可以作为 Angular 开发人员的一个例子。

Material Design 作为一个非常流行的设计语言,它有多个版本的实现。React 版的 Material Design 有着很高的人气,大家可以自行对比,我就不赘述了,以免引起无谓的争吵,进而扯到框架层面。我可以说一下自己的感受,Angular Material 的交互更加流畅,细节做的更好。

Angular Material 组件库虽然很优秀,但是却被带上了只适合做 C 端界面的帽子。这也是我刚开始不敢选择 Angular Material 的一个原因。但是编写 ng-matero 的过程中,随着对 Angular Material 的深入了解,我发现这种说法稍显狭隘甚至产生了一定的误导,所以我希望这篇文章可以让大家对 Angular Material 有一个更加正确的认识。接下来我会从相对宏观的角度介绍 Angular Material 设计的一些亮点,并且简单介绍 Angular Material 的一些使用技巧。

题外话:为什么 ng-matero 会选择 Angular Material?

抛开官方提到的几点不谈。首先我是那种比较激进的开发者,对于先进的设计理念,我都有跃跃欲试的执念。国内的 Element UI 以及 Ant Design 都是 Bootstrap 3 时代的风格。随着业务人员对界面细致紧凑的要求越来越高,我发现 Material 的设计风格更加符合需求,层次感更强。不过最主要的还是 Material Design 的交互更吸引我。另外,Angular Material 的样式是基于 Sass 编写,而我最喜欢的也是 Sass,所以基于 Angular Material 编写 ng-matero 就是命运的归宿。顺便插一句,如果大家纠结用 Sass 还是 Less,可以看一下这篇文章 CSS 预处理器中的循环,个人不建议用 Less,请原谅我无意引战??。

少即是多

Less is more(少即是多)—— 密斯·凡德罗

我想很多人对 Angular Material 望而却步的原因之一就是它的组件看上去有点少。然而在一般的业务中这些组件已经够用。除了常用组件之外,Angular Material 还有一个组件开发包 CDK。在设计界有一句名言“少即是多”,苹果的产品就是最好的证明。把这句名言用在 Angular material 上丝毫不为过,其实除了我们看到的组件之外,Material 还有一些隐藏组件,比如可以用 menu 组件构造 popover,我会在下文中介绍。

丰富的颜色

Material Design 的亮点之一就是拥有非常丰富的颜色值,其实 Angular Material 的颜色变量比官方定义的色值还要多一些。大家可以点击 ng-matero 的 colors 页面 查看。ng-matero 也有所有颜色值对应的 colors helper,可以更加方便的创建丰富多彩的按钮或标签。Angular Material 的颜色定义严谨且优雅。以下是红色值的变量。

$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 '[email protected]/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 有关的样式工具,包括变量functionmixin,都可以在 theming 文件中找到。

除了上面提到的主题定制 functionmixin 之外,我们还可以使用 mat-elevation() 轻松制作 MD 阴影。另外我们还可以使用 $swift-ease-out-timing-function$mat-fast-out-slow-in-timing-function 这些动画变量实现和 MD 一样的动画效果。

基于这套工具集,我们可以很容易的搭建和 MD 风格相统一的界面。

极简的 API

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 的原因之一。

响应式布局

Angular Material 并没有布局组件。但是不用担心,官方出品了一款基于指令布局的神器 flex-layout,它是专门为 Angular 设计的。基于指令的布局方式和 Bootstrap 的栅格布局是两种不同的设计理念。flex-layout 的使用很简单,可以很快上手,熟悉之后你一定会喜欢这种布局方式。

总结

文章篇幅有限,以我浅薄的资历还无法将 Angular Material 的设计之美剖析的面面俱到,但是如果大家通过这篇文章能够更好的了解 Angular Material 或者对 Angular Material 产生了一点兴趣,我也算是做了一件好事。

任何组件库都无法满足所有业务需求,如果你无法在 Angular Material 中找到可用的组件,你可以尝试第三方组件,或者可以将 ng-zorro-antd 按模块单独引入。在此推荐一些优秀的第三方组件。

如果大家喜欢 Angular 或者对 Angular Material 感兴趣,欢迎进群讨论!

原文地址:https://www.cnblogs.com/nzbin/p/11424801.html

时间: 2024-10-14 18:12:26

Angular Material 的设计之美的相关文章

Angular Material主题配置

前言 Angular Material是基于metarial design 的angular UI.当我们使用Material的时候,自然而然的就需要去使用它的主题颜色.这个时候我们就得选择自己配置还是使用它的默认主题.注意:在使用Angular Material的时候请先引入(angular-material.css).(angular.min.js.angular-animate.js.angular-aria.js.angular-material.js). 默认调色板 在介绍Materi

Angular Material串串学客户端开发 2 - Node.js模块加载机制Require()

题外话解一下博客标题,因为第一篇文章评论中,有人质疑离题很远,说了半天和Angular Material没有半毛关系.其实我的的中心在后半句<串串学客户端开发>. require() 不要把这里的Require()和RequireJS混为一谈.不过有意思的是,Typescript的模块定义,甚至同时支持这两种模块机制. 导入和使用外部模块,只是简单的一句require(),看看angular/material/docs下的编译文件gulpfile.js的代码片段.对模块导入和使用有个直观的感觉

实现Instagram的Material Design设计(2)- 评论窗口实现

实现Instagram的Material Design设计系列第一篇http://blog.csdn.net/tongsdroid/article/details/51567583 这篇文章是一个实现Instagram的Material Design设计系列的第二篇文章,今天,我们将实现主页和评论活动之间的过渡(在概念录像显示为9秒之间13).我们将跳过按钮效果(涟漪,发送完成动画等),只关注发表评论的Acitvity进入和退出动画. 这是在今天的文章中描述(适用于Android5.0和之前的版

Angular问题03 @angular/material版本问题

1 问题描述 应用使用 angular4在使用@angular/material时,若果在导入模块时使用mat开头,就会报错. 2 问题原因 @angular/material版本出现问题,@angular/material 从版本5开始就必须要angular5的核心依赖:想要在angular5之前版本中的应用中使用@angular/material,要么更改@angular/material的版本(降低版本),例如:cnpm i --save @angular/[email protected

投稿007期|令人震惊到发指的PyObject对象代码设计之美

前言 最近在重温经典漫画<SlamDunk>的全国大赛篇,其中的一个情形可以很好的诠释虎躯一震这个状态--当樱木看到流川枫一次高难度投篮时内心的感受:"经过两万次射球练习后,樱木首次明白到流川枫这一球是相当厉害的,那正是他在两万次射球练习之中,经常在他脑海中出现的理想射球姿势". 言归正传,其实对大多数程序开发人员来说,以上这个场景的感慨状态有时候也出现在我们看到经典代码的时候.最近正在思考关于Python语言的源生设计机制,有个问题不知道大家是否也有思考过:我们知道Pyt

(Angular Material)用Autocomplete打造带层级分类的DropDown

效果如下图 代码实现 1.导入模块 import {MatAutocompleteModule} from '@angular/material/autocomplete'; @NgModule({   imports:[       MatAutocompleteModule    ] }) 2.编写List内容 this.memberNameList = [ { onOffDist: 'オン', items: ['丁1', '徐2', '僑3'] }, { onOffDist: 'オフ',

Android Material Design-Creating Apps with Material Design(用 Material Design设计App)-(零)

转载请注明出处:http://blog.csdn.net/bbld_/article/details/40400031 翻译自:http://developer.android.com/training/material/index.html 前言 这篇文章是官方material design文档翻译的第一篇.关于material design须要了解的知识能够參阅这本中文版的译文电子书. Material design是一种跨平台的为了视觉.动作.交互设计的综合指南.要在你的Android应用

Angular简易分页设计

之前网站的后台管理为了图快,把Jquery写的前台页面使用的分页插件,套到Angular中使用.现在后台的小编说这东西有时候翻页失败,而插件代码十分复杂,无法定位bug进行修改,也无法保证修改后不会出现别的bug,干脆舍弃插件,自己写一个. 设计时,我大概看了一下插件的代码,基本思路就是通过数据处理判断,然后通过字符串拼接,生成新的dom元素.而我们需要的分页是在Angular中运行,应当尽量避免这种做法.怎么简单怎么来,我们固定一次只显示7个页码,不需要动态增删元素. <ul> <li

《工业设计之美》——邱丰顺

一.工业设计可以/应该为企业做哪些工作 邱丰顺工作案例:2007-2012年,以国际公司的工业设计经验协助创维彩电从中国走向国际. 其中,2007-2008产品设计,2008-2010设计组织+流程再造,2010-2012建立创新产品研发机制 2007年创维面临的主要难题(skyzworth's problems) 1.品牌形象不清晰(Brand/product identity blur) 2.产品大部分以模仿国际品牌为主(Market follower(copy leadin brand))