• Angular Material design设计


    官网:

    https://material.io/design/

    https://meterial.io/components

    优秀的Meterial design站点:

    http://materialdesignblog.com/

    并不是万能的,都有约束条件。

    优点:兼容性好,可扩展性强,可测试性好,对主题的支持好。

    缺点:组件不是特别丰富。

    安装:

    //其它方式
    $ sudo cnpm i --save @angular/material@2.0.0-beta.7

    $ sudo yarn add @angular/material --save

    $ npm i @angular/material --save

    安装的版本是"@angular/material": "^7.1.0",

    有个依赖要手动安装

    $ sudo yarn add @angular/cdk@6.4.6 --save

    一、相关报错 

    1、控制台报警告:Could not find Angular Material core theme。

    在styles.scss中引入angular materail主题:

    @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

    内建主题有这几种:

    可以用scss自定义主题。

    2、ERROR Error: Found the synthetic listener @transform.start. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.

    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    3、mat-toolbar,mat-sidenav和mat-sidenav-container不是已知的元素?
    Uncaught Error: Template parse errors: 'mat-icon' is not a known element: 1. If 'mat-icon' is an Angular component, then verify that it is part of this module.
    应该将模块导入与组件相关的module.ts文件中。比如我是在header这个组件中用到了mat-icon,而我的header组件是放在core Module中的,那就要在core Module中去import MatIconModule,而不是在app.module中引入。
    4、ERROR Error: Could not find HttpClient provider for use with Angular Material icons.
    使用SVG Icon的时候依赖Http。需要导入HttpClient。
    5、NewTaskComponent.html:14 ERROR Error: MatDatepicker: No provider found for DateAdapter. You must import one of the following modules at your application root: MatNativeDateModule, MatMomentDateModule, or provide a custom implementation.
    使用DatePicker的时候同时要导入MatNativeDateModule用作DateFormat。
    6、core.es5.js:178 Could not find HammerJS. Certain Angular Material components may not work correctly.
    移动端用HammerJS去处理一些事件。
    $ npm install --save hammerjs
    安装好以后在coreModule中
    import 'hammerjs';

    二、Material组件

    1、SidebarComponent侧边栏导航:

    https://material.angular.io/components/sidenav/overview

    <mat-sidenav-container> 
      <mat-sidenav #sidenav>
        <app-sidebar></app-sidebar>
      </mat-sidenav>
      <div class="site">
        <header>
          <app-header></app-header>
        </header>
        <main>
          <button (click)="sidenav.open()">打开侧边栏</button>
        </main>
        <footer>
          <app-footer></app-footer>
        </footer>
      </div>
    </mat-sidenav-container>
    View Code

    根容器<mat-sidenav-container>

    • over模式【默认】
    <mat-sidenav #sidenav mode="over">

    • side模式
    <mat-sidenav #sidenav mode="side">并排显示

    • push模式
    <mat-sidenav #sidenav mode="push">相当于over和side的结合

    • position="end" 
      <mat-sidenav #sidenav mode="push" position="end">

    侧边栏跑右边了,默认start。最多可以有2个侧边栏。

    <mat-sidenav-container>
      <mat-sidenav #sidenav1 mode="push" position="end">
        <app-sidebar></app-sidebar>
      </mat-sidenav>
      <mat-sidenav #sidenav2 mode="push" position="start">
          <app-sidebar></app-sidebar>
        </mat-sidenav>
      <div class="site">
        <header>
          <app-header></app-header>
        </header>
        <main>
          <button (click)="sidenav1.open()">打开右边侧边栏</button>
          <button (click)="sidenav2.open()">打开左边侧边栏</button>
        </main>
        <footer>
          <app-footer></app-footer>
        </footer>
      </div>
    </mat-sidenav-container>
    View Code

     

    • toogle方法:类似open
    <button (click)="sidenav.toggle()">打开侧边栏</button>
    <mat-sidenav-container>
      <mat-sidenav #sidenav mode="side" >
        <app-sidebar></app-sidebar>
      </mat-sidenav>
      <div class="site">
        <header>
          <app-header></app-header>
        </header>
        <main>
          <button (click)="sidenav.toggle()">打开侧边栏</button>
        </main>
        <footer>
          <app-footer></app-footer>
        </footer>
      </div>
    </mat-sidenav-container>
    View Code

    2、Toolbar完成头部和尾部

    https://material.angular.io/components/toolbar/overview

    用于头部,标题栏

    颜色primary紫色,accent黄色,warn红色。

    主色:primary

    配色:accent

    用官方的material io 的COLOR TOOL可以调出合适的颜色。主色深紫,辅助色黄色效果如下。

     

    1、居中用flex怎么实现?

    在想居中元素两边都放了自动扩大充满的元素。

    在styles.scss中加入

    .fill-remaining-space {
      // 使用 flexbox 填充剩余空间
      // @angular/material 中的很多控件使用了 flex 布局
      flex: 1 1 auto;
    }
    <mat-toolbar color="primary">
      <span class="fill-remaining-space"></span>
      <span>&copy; strof 版权声明</span>
      <span class="fill-remaining-space"></span>
    </mat-toolbar>

    2、两行内容怎么实现?

    mat-toolbar-row也是flex容器。 用<mat-toolbar-row>支持多行。
    <mat-toolbar color="primary">
      <mat-toolbar-row>
        <span class="fill-remaining-space"></span>
        <span>&copy; starof 版权声明</span>
        <span class="fill-remaining-space"></span>
      </mat-toolbar-row>
      <mat-toolbar-row>
        <span class="fill-remaining-space"></span>
        <span>这是第二行</span>
        <span class="fill-remaining-space"></span>
      </mat-toolbar-row>
    </mat-toolbar>

    3、菜单button调出左边sidebar

    问题,头部的菜单按钮不知道sidebar在哪里,涉及到父子组件通信

    4、 用一个icon代替菜单2个文字

    https://material.angular.io/components/icon/overview

    使用图标字体,基于字体的,好处占用资源小,矢量图,内建material icon支持。

    线用mat-icon,导入MatIconModule。
    在index.html中引入material-icon字体库。参考:https://google.github.io/material-design-icons/
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    使用
    <button mat-icon-button (click)="openSidebar()">
            <mat-icon class="material-icons">menu</mat-icon>
    </button>

    想要使用其它图标直接,去https://material.io/tools/icons/ 找到图标对应文字替换掉即可。

    5、MatIcon也支持SVG图标。

    找SVG资源,http://iconfont.cn/ 阿里爸爸矢量图标库

    把下载好的SVG放在项目的assets中。

    最终效果:

    实现
      constructor(private iconRegistry: MatIconRegistry,
        private sanitizer: DomSanitizer) {
        iconRegistry.addSvgIcon('gift', sanitizer.bypassSecurityTrustResourceUrl('assets/gift.svg'));
      }
    <mat-icon svgIcon="gift"></mat-icon>

    问题,每次使用一个新图标都要注册一遍。图标分散在各个组件的constructor中,难以维护。

    更好的做法:

    在app下创建一个utils目录,在utils里建一个svg.util.ts。

    import { MatIconRegistry } from "@angular/material";
    import { DomSanitizer } from "@angular/platform-browser";
    
    export const loadSvgResources = (ir: MatIconRegistry, ds: DomSanitizer) => {
      ir.addSvgIcon("gift", ds.bypassSecurityTrustResourceUrl("assets/gift.svg"));
    };

    不在组件的constructor里导入里,在core module里只加载一次。

    export class CoreModule {
      constructor(
        @Optional() @SkipSelf() parent: CoreModule, //加上@SkipSelf()注解
        ir: MatIconRegistry,
        ds: DomSanitizer
      ) {
        if (parent) {
          throw new Error("模块已经存在,不能再次加载");
        }
        loadSvgResources(ir, ds);
      }
    }

    这样其它页面只要用就可以,解决了装载资源分散的问题。

    3、Input组件matInputModule

    可以通过color取值warn,accent等来改变input输入框的颜色。

    可以通过floatLabel取值float,always,auto来改变Label显示方式。

    可以设置hintLabel或者<mat-hint>来添加更多提示信息。

    可以通过给<mat-form-field>里的元素设置matSuffix指令来给输入框添加后缀,设置matPrefix指令加前缀。

    https://material.angular.io/components/form-field/overview

    <mat-form-field class="example-full-width" color="warn" floatLabel="auto" hintLabel="Max 10 characters">
                <input #input matInput placeholder="您的email">
                <span matSuffix>@gmail.com</span>
                <mat-hint align="end">{{input.value?.length || 0}}/10</mat-hint>
    </mat-form-field>

    <mat-error> :只有验证不通过时才出现,对两种类型表单都是。
    <mat-hint>:和<mat-error>在同一个位置去显示,当error显示时,hint会隐藏。 

    4、Card组件和Button组件 

    raised:3D效果。
    icon:透明的圆形button,图片是hover上去的效果。
    fab:fast action button.
     
    mat-button Rectangular text button w/ no elevation
    mat-raised-button Rectangular contained button w/ elevation
    mat-flat-button Rectangular contained button w/ no elevation
    mat-stroked-button Rectangular outlined button w/ no elevation
    mat-icon-button Circular button with a transparent background, meant to contain an icon
    mat-fab Circular button w/ elevation, defaults to theme's accent color
    mat-mini-fab
    Card适合图文形式突出某一主题。https://material.angular.io/components/card/overview
      <mat-card class="example-card">
        <mat-card-header>
          <mat-card-title>每日佳句</mat-card-title>
          <mat-card-subtitle>满足感在于不断的努力,而不是现有成就。全心努力定会胜利满满。</mat-card-subtitle>
        </mat-card-header>
        <img mat-card-image src="/assets/images/quote_fallback.jpg" alt="">
        <mat-card-content>
          Satisfaction lies in the effort, not in the attainment. Full effort is full victory.
        </mat-card-content>
      </mat-card>
    View Code

    5、List

    https://material.angular.io/components/list/overview

    包括都行列表,带图标列表,带头像列表,密集列表(dense list)和多段列表。

    分为<mat-list> 和<mat-nav-list>

    在侧滑菜单中使用List。

    matNavList鼠标hover上去会有高亮效果。

    <mat-nav-list>
      <h3 mat-subheader>项目</h3>
      <mat-list-item>
        <mat-icon mat-list-icon svgIcon="projects"></mat-icon>
        <h4 mat-line>项目首页</h4>
        <p mat-line mat-subheader> 查看您的所有项目</p>
      </mat-list-item>
      <h3 mat-subheader>日历</h3>
      <mat-list-item>
        <mat-icon mat-list-icon svgIcon="month"></mat-icon>
        <h4 mat-line>月视图</h4>
        <p mat-line mat-subheader> 按月查看您的任务</p>
      </mat-list-item>
      <mat-list-item>
        <mat-icon mat-list-icon svgIcon="week"></mat-icon>
        <h4 mat-line>周视图</h4>
        <p mat-line mat-subheader> 按周查看您的任务</p>
      </mat-list-item>
      <mat-list-item>
        <mat-icon mat-list-icon svgIcon="day"></mat-icon>
        <h4 mat-line>日视图</h4>
        <p mat-line mat-subheader> 按天查看您的任务</p>
      </mat-list-item>
    </mat-nav-list>
    View Code

    Dense list会让列表的字体shrink来显示更多内容。用法<mat-nav-list dense>。

    把日式图的图标改变成当天的日前,在svg.util.ts中加入提前准备好的30天日期day1.svg到day3-.svg. 

    import { MatIconRegistry } from "@angular/material";
    import { DomSanitizer } from "@angular/platform-browser";
    
    export const loadSvgResources = (ir: MatIconRegistry, ds: DomSanitizer) => {
      const imgDir = "assets/img";
      const sidebarDir = `${imgDir}/sidebar`;
      const dayDir = `${imgDir}/days`;
      ir.addSvgIcon(
        "day",
        ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/day.svg`)
      );
      ir.addSvgIcon(
        "month",
        ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/month.svg`)
      );
      ir.addSvgIcon(
        "project",
        ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/project.svg`)
      );
      ir.addSvgIcon(
        "projects",
        ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/projects.svg`)
      );
      ir.addSvgIcon(
        "week",
        ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/week.svg`)
      );
    
      const days =[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
      days.forEach((d)=>{
        ir.addSvgIcon(
          `day${d}`,
          ds.bypassSecurityTrustResourceUrl(`${dayDir}/day${d}.svg`)
        );
      });
    };
    View Code

    在sidebar.component.ts中引入一个类库day-fns。 

    npm uninstall --save date-fns //先安装date-fns
    npm install --save-dev @types/date-fns //再date-fns针对typescript也可以使用的类型

    import { Component, OnInit } from '@angular/core';
    import {getDate} from 'date-fns'; //getDate取得是一个月的几号
    
    @Component({
      selector: 'app-sidebar',
      templateUrl: './sidebar.component.html',
      styleUrls: ['./sidebar.component.scss']
    })
    export class SidebarComponent implements OnInit {
      today = 'day';
      constructor() { }
    
      ngOnInit() {
        this.today=`day${getDate(new Date())}`; //today对应icon的名字
      }
    
    }

    模版中icon对应到today。

    <mat-icon mat-list-icon [svgIcon]="today"></mat-icon>

    6、GridList

    <mat-grid-list cols="8" rowHeight="1:1">
            <mat-grid-tile colspan="2">
              1
            </mat-grid-tile>
            <mat-grid-tile>
              2
            </mat-grid-tile>
            <mat-grid-tile>
              3
            </mat-grid-tile>
            <mat-grid-tile>
              4
            </mat-grid-tile>
            <mat-grid-tile rowspan="2">
              5
            </mat-grid-tile>
            <mat-grid-tile>
              6
            </mat-grid-tile>
            <mat-grid-tile>
              7
            </mat-grid-tile>
            <mat-grid-tile>
              8
            </mat-grid-tile>
            <mat-grid-tile>
              9
            </mat-grid-tile>
            <mat-grid-tile>
              10
            </mat-grid-tile>
            <mat-grid-tile>
              11
            </mat-grid-tile>
            <mat-grid-tile>
              12
            </mat-grid-tile>
            <mat-grid-tile>
              13
            </mat-grid-tile>
            <mat-grid-tile>
              14
            </mat-grid-tile>
          </mat-grid-list>
    View Code

    注册页面头像列表可以用GridList实现。

    7、dialog

    https://material.angular.io/components/dialog/overview

    对话框很特殊,和menu一样需要在模块中的entryComponents中声明。

    由于它们是需要事先完全隐藏,或者隐藏一部分。一开始模块加载的时候是看不到dialog的,点击按钮才能弹出。对于这种情况,需要一个预加载,就需要放在模块的entryComponents中。

    1、从调用者向Dialog传递数据

    传递数据:

    不能像其它组件一样,通过路由去传递数据。需要从它的调用者去写。

    在按钮的click事件中写:

    const dialogRef = dialog.open(YourDialog, {data:'Your data'});

    接收数据:

    在Dialog的构造中注入MD_DIALOG_DATA就可以取得数据。

    constructor(@Inject(MAT_DIALOG_DATA) private data: any) { }

    2、在Dialog把数据往回传,传给调用者。

    //注入MatDialogRef 
     constructor(@Inject(MAT_DIALOG_DATA) private data: any,
        public dialogRef: MatDialogRef<NewProjectComponent>, ) { }
    //在点击保存按钮时候发送数据
      onSave() {
        this.dialogRef.close('I received your message');
      }
    

    //调用者open的时候拿到一个引用,注册afterClosed事件返回一个Observable openNewProjectDialog() { // this.dialog.open(NewProjectComponent,{data:'this is a dialog'}); const dialogRef = this.dialog.open(NewProjectComponent, { data: "this is a dialog" }); dialogRef.afterClosed().subscribe((result)=>{ console.log(result); }); }

    3、Dialog样式支持主题

    //注入OverlayContainer  
    constructor(@Inject(MAT_DIALOG_DATA) private data: any,
        public dialogRef: MatDialogRef<NewProjectComponent>,
        private oc: OverlayContainer) { }
    
    //通过传入dark来切换class
      ngOnInit() {
        console.log(JSON.stringify(this.data));
        this.oc.themeClass = this.data.dark ? 'myapp-dark-theme' : 'null';
      }

    报错:ERROR in src/app/project/new-project/new-project.component.ts(18,13): error TS2339: Property 'themeClass' does not exist on type 'OverlayContainer'.

     参考:

    https://gist.github.com/tomastrajan/ee29cd8e180b14ce9bc120e2f7435db7

    8、autoComplete 

    https://material.angular.io/components/autocomplete/overview

     

    <form class="example-form">
      <mat-form-field class="example-full-width">
        <input type="text" placeholder="Assignee" aria-label="Assignee" matInput [formControl]="myControl" [matAutocomplete]="auto">
        <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
          <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
            {{option.name}}
          </mat-option>
        </mat-autocomplete>
      </mat-form-field>
    </form>

    displayWith传入一个函数,指明具体怎样显示

      displayFn(user?: User): string | undefined {
        return user ? user.name : undefined;
      }

    9、menu

    <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>

    10、复选框,单选组件和下拉框

    <mat-checkbox>和<mat-radio>和<mat-select>

    checkbox还要chenged事件处理

      <mat-checkbox [checked]="item.completed" class="status">  </mat-checkbox>

    Tooptip

      <div class="content" mat-line [ngClass]="{'completed':item.completed}">
        <span [matTooltip]="item.desc">{{item.desc}}</span>
      </div>

    11、DatePicker

    https://material.angular.io/components/datepicker/overview 

    <mat-form-field>
      <input matInput [matDatepicker]="picker" placeholder="Choose a date">
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
    </mat-form-field>

  • 相关阅读:
    第十六节:Linq用法大全(四)
    第十五节:EF Core大数据量处理(一)之EFCore.BulkExtensions
    第十四节:EF Core性能优化
    查看mysql执行的线程,并杀掉他
    docker安装与卸载
    新手根据菜鸟教程安装docker,从No package docker-io available开始遇到的坑...(转)
    MySQL启动出现The server quit without updating PID file错误解决办法
    Linux下彻底卸载mysql详解
    Linux 下的 Redis 安装 && 启动 && 关闭 && 卸载
    Linux安装mysql
  • 原文地址:https://www.cnblogs.com/starof/p/9074333.html
Copyright © 2020-2023  润新知