zoukankan      html  css  js  c++  java
  • [转]angular2封装material2对话框组件

    本文转自:https://www.jianshu.com/p/da9978e25566

    1. 说明

    angular-material2自身文档不详,控件不齐,使用上造成了很大的障碍。这里提供一个方案用于封装我们最常用的alert和confirm组件。

    2. 官方使用方法之alert

    2.1 编写alert内容组件

    @Component({
      template : `<p>你好</p>`
    })
    export class AlertComponent {
    
        constructor(){
        }
    }
    

    2.2 在所属模块上声明

    //必须声明两处
    declarations: [ AlertComponent],
    entryComponents : [ AlertComponent]
    

    2.3. 使用MdDialg.open方法打开

    //注入MdDialog对象
    constructor(private mdDialog : MdDialog) { }
    //打开
    this.mdDialog.open(AlertComponent)
    

    3. 官方使用方法之confirm

    1. 编写confirm内容组件
    @Component({
      template : `<div md-dialog-title>'确认操作'</div>
                  <div md-dialog-content>确认执行操作?</div>
                  <div md-dialog-actions>
                    <button md-button (click)="mdDialogRef.close('ok')">确认</button>
                    <button md-button (click)="mdDialogRef.close('cancel')">取消</button>
                  </div>`
    })
    export class ConfirmComponent {
        constructor(private mdDialogRef : MdDialogRef<DialogComponent>){ }
    }
    
    1. 在所属模块上声明
    //必须声明两处
    declarations: [ ConfirmComponent],
    entryComponents : [ ConfirmComponent]
    
    1. 使用MdDialog.open打开并订阅相关事件
    //注入MdDialog对象
    constructor(private mdDialog : MdDialog) { }
    //打开
    this.mdDialog.open(ConfirmComponent).subscribe(res => {
        res === 'ok' && dosomething
    });
    

    4. 分析

    如2、3所示,使用material2的对话框组件相当繁琐,甚至仅仅打开一个不同的alert都要声明一个独立的组件,可用性很差。但也不是毫无办法。

    MdDialog.open原型:

    open<T>(componentOrTemplateRef: ComponentType<T> | TemplateRef<T>, config?: MdDialogConfig): MdDialogRef<T>;
    

    其中MdDialogConfig:

    export declare class MdDialogConfig {
        viewContainerRef?: ViewContainerRef;
        /** The ARIA role of the dialog element. */
        role?: DialogRole;
        /** Whether the user can use escape or clicking outside to close a modal. */
        disableClose?: boolean;
        /** Width of the dialog. */
        width?: string;
        /** Height of the dialog. */
        height?: string;
        /** Position overrides. */
        position?: DialogPosition;
        /** Data being injected into the child component. */
        data?: any;
    }
    

    具体每一个配置项有哪些用途可以参考官方文档,这里data字段,说明了将会被携带注入子组件,也即被open打开的component组件。怎么获取呢?

    config : any;
    constructor(private mdDialogRef : MdDialogRef<AlertComponent>){
        this.config = mdDialogRef.config.data || {};
    }
    

    有了它我们就可以定义一个模板型的通用dialog组件了。

    5. 定义通用化的组件

    //alert.component.html
    <div class="title" md-dialog-title>{{config?.title || '提示'}}</div>
    <div class="content" md-dialog-content>{{config?.content || ''}}</div>
    <div class="actions" *ngIf="!(config?.hiddenButton)" md-dialog-actions>
      <button md-button (click)="mdDialogRef.close()">{{config?.button || '确认'}}</button>
    </div>
    
    //alert.component.scss
    .title, .content{
      text-align: center;
    }
    .actions{
      display: flex;
      justify-content: center;
    }
    
    
    //alert.component.ts
    @Component({
      selector: 'app-alert',
      templateUrl: './alert.component.html',
      styleUrls: ['./alert.component.scss']
    })
    export class AlertComponent {
    
      config : {};
    
      constructor(private mdDialogRef : MdDialogRef<AlertComponent>){
        this.config = mdDialogRef.config.data || {};
      }
    
    }
    

    我们将模板的一些可置换内容与config一些字段进行关联,那么我们可以这么使用:

    constructor(private mdDialog : MdDialog) { }
    
    let config = new MdDialogConfig();
    config.data = {
        content : '你好'
    }
    this.mdDialog.open(AlertComponent, config)
    

    依然繁琐,但至少我们解决了对话框组件复用的问题。

    我们可以声明一个新的模块,暂且起名为CustomeDialogModule,然后将component声明在此模块里,再将此模块声明到AppModule,这样可以避免AppModule的污染,保证我们的对话框组件独立可复用。

    6. 二次封装

    如果仅仅是上面的封装,可用性依然很差,工具应当尽可能的方便,所以我们有必要再次进行封装

    首先在CustomDialogModule建一个服务,暂且起名为CustomDialogService

    @Injectable()
    export class CustomDialogService {
    
      constructor(private mdDialog : MdDialog) { }
    
      //封装confirm,直接返回订阅对象
      confirm(contentOrConfig : any, title ?: string) : Observable<any>{
        let config = new MdDialogConfig();
        if(contentOrConfig instanceof Object){
          config.data = contentOrConfig;
        }else if((typeof contentOrConfig) === 'string'){
          config.data = {
            content : contentOrConfig,
            title : title
          }
        }
        return this.mdDialog.open(DialogComponent, config).afterClosed();
      }
    
      //同
      alert(contentOrConfig : any, title ?: string) : Observable<any>{
        let config = new MdDialogConfig();
        if(contentOrConfig instanceof Object){
          config.data = contentOrConfig;
        }else if((typeof contentOrConfig) === 'string'){
          config.data = {
            content : contentOrConfig,
            title : title
          }
        }
        return this.mdDialog.open(AlertComponent, config).afterClosed();
      }
    

    我们把它注册在CustomDialogModule里的provides,它就可以被全局使用了。

    用法:

    constructor(dialog : CustomDialogService){}
    
    this.dialog.alert('你好');
    this.dialog.alert('你好','标题');
    this.dialog.alert({
        content : '你好',
        title : '标题',
        button : 'ok'
    });
    this.dialog.confirm('确认吗').subscribe(res => {
        res === 'ok' && dosomething
    });
    

    按照这种思路我们还可以封装更多组件,例如模态框,toast等



    作者:blurooo
    链接:https://www.jianshu.com/p/da9978e25566
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    LNMP架构三
    LNMP架构二
    LNMP架构
    LAMP架构三
    LAMP架构二
    LAMP架构
    rsync工具介绍
    mysqldump备份单表数据
    阿铭每日一题 day 14 20180125
    阿铭每日一题 day 13 20180124
  • 原文地址:https://www.cnblogs.com/freeliver54/p/9741786.html
Copyright © 2011-2022 走看看