跳转到主要内容

TypeScript的装饰器可以帮助您减少Angular应用程序的样板文件!

medium/custom-decorator at main · TimJ0212/medium

Contribute to TimJ0212/medium development by creating an account on GitHub.

github.com

装饰器是Angular开发人员已知的功能。对于像@NgModule或@Component Angular这样的已知装饰器,装饰器本身正在提升生产力。你也能做到!

你确定吗?

我想在对应用程序进行资源密集型或关键性操作之前,您几乎随时都会看到这个问题。

首先,您将实现一个方法,并在每次请求用户确认时调用它。这还不错,但通过定期调用方法,您可以在代码中的任何地方都得到方法调用。如果有一个注释,它会自动询问用户并处理响应,那不是很好吗?

(即使你在想,我也不需要这个,注释适合所有类型的重复工作,比如auth或其他东西。)

让我们开始吧

  • 使用ng new创建新的角度工作空间
  • 使用ng Add@Angular/Material添加角度材质
  • 创建一个简单的对话框组件:ng g组件组件/简单对话框
  • 创建一个名为confirmable.decorator.ts的文件(在我的例子中是在共享/decorator目录中)

装饰器

import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { SimpleDialogComponent } from '../../components/simple-dialog/simple-dialog.component';
import { AppModule } from '../../app.module';
import { Type } from '@angular/core';

export interface ConfirmableDecoratorOptions {
  title?: string;
  text?: string;
}

export function Confirmable() {
  return (
    target: Object,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) => {
    const originalMethod = descriptor.value;
    const config: ConfirmableDecoratorOptions = {
      title: 'Confirmationen needed',
      text: 'Are you sure?',
    };

    descriptor.value = async function (...args: any[]) {
      const dialog: MatDialog = AppModule.INJECTOR.get<MatDialog>(
        MatDialog as Type<MatDialog>
      );
      const dialogRef: MatDialogRef<SimpleDialogComponent> = dialog.open(
        SimpleDialogComponent,
        {
          data: {
            title: config.title,
            text: config.text,
          },
        }
      );

      dialogRef.afterClosed().subscribe((result) => {
        if (result === true) {
          return originalMethod.apply(this, args);
        }
      });
    };
    return descriptor;
  };
}

简单的对话框

import { Component, Inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { MatButtonModule } from '@angular/material/button';

export type DialogData = {
  title: string;
  text: string;
};

@Component({
  selector: 'app-simple-dialog',
  standalone: true,
  imports: [CommonModule, MatDialogModule, MatButtonModule],
  template: `
    <h1 mat-dialog-title>{{ data.title }}</h1>
    <div mat-dialog-content>
      {{ data.text }}
    </div>
    <div mat-dialog-actions>
      <button [mat-dialog-close]="false" mat-button>Cancel</button>
      <button [mat-dialog-close]="true" mat-button>Ok</button>
    </div>
  `,
})
export class SimpleDialogComponent {
  constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}

 

对应的模块(在我的情况下,两者都是AppModule)

import { Injector, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatButtonModule,
    MatDialogModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {
  static INJECTOR: Injector;

  constructor(injector: Injector) {
    AppModule.INJECTOR = injector;
  }
}

现在,您可以在任何您喜欢的方法上添加decorator

import { Component } from '@angular/core';
import { Confirmable } from './shared/decorators/confirmable.decorator';

@Component({
  selector: 'app-root',
  template: `<button (click)="doSomething()" color="primary" mat-raised-button>
      Do Something
    </button>
    <div>{{ this.confirmed }}</div> `,
})
export class AppComponent {
  public confirmed: boolean = false;

  @Confirmable() // <-- Here it is!
  public doSomething(): void {
    this.confirmed = true;
  }
}

运行npm-Run-start,如果您在localhost:4200上打开浏览器,您的应用程序应该是这样的

如果你按下蓝色按钮,你会看到一个对话框,要求确认。如果取消,则不会调用该方法。但只要按下“确定”,应用程序流程就会继续。

 

文章链接