1 minute read

学んだこと

複数のデコレータを同時に使う方法

  • デコレータ
    • 下から上に実行される
  • デコレータファクトリー
    • 上から下に実行される
// この関数がデコレータファクトリ
function Logging(message: string){
  return function (constructor: Function){
    console.log(message)
  }
}

// ここでフレームワークを作成
function Component(template: string, selector: string){
  // 新しくインスタンスを生成
  // templeteにはHTMLが格納されているため、innerHTMLにいれる
  // textContentにはインスタンスで生成したnameをそのまま渡す
  return function(constructor: { new(...args: any): {name: string} }){
    const mountedElement = document.querySelector(selector);
    const instance = new constructor();
    if(mountedElement){
      mountedElemet.innerHTML = templete;
      mountedElement.querySelector("h1")!.textContent = instance.name;
    }
  }
}

// 複数定義しているため、デコレータを複数用意することは可能
@Component("<h1></h1>", "#app")
@Logging("LoggingUser")
Class User{
  name = "Quill";
  constructor(){
    console.log("User was created!")
  }
}
  • html 側
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="dist/decorator.js" defer></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

戻り値にクラスを指定して、新しいクラスを作り出す方法

function Logging(message: string){
  return function (constructor: Function){
    console.log(message)
  }
}

function Component(template: string, selector: string){

  // 戻り値にクラスを返す
  // コンストラクタで設定した内容をそのままコピペしてextendsにつける
  return function<T extends { new(...args: any): {name: string} } >(constructor: { new(...args: any): {name: string} }){

    // ここでクラスを返すようにする
    return class extends constructor {
      constructor(...args: any) {
        super(...args);
        const mountedElement = document.querySelector(selector);
        const instance = new constructor();
        if(mountedElement){
          mountedElemet.innerHTML = templete;
          mountedElement.querySelector("h1")!.textContent = instance.name;
        }
      }
    }
  }
}

@Component("<h1></h1>", "#app")
@Logging("LoggingUser")
Class User{
  name = "Quill";
  constructor(){
    console.log("User was created!")
  }
}

プロパティデコレータ

  • デコレータの前にプロパティデコレータが最初に実行される ``` // プロパティは2つ引数を設定する // 1つ目: プロトタイプ(インスタンスが共有する関数やプロパティの土台、設計図のようなもの) // 2つ目: キー情報 function PropertyLogging(target: any, propertyKey: string){ console.log() }

@Component(“<h1></h1>”, “#app”) @Logging(“LoggingUser”) Class User{ @PropertyLogging name = “Quill”; constructor(){ console.log(“User was created!”) } }

### メソッドデコレータ

function PropertyLogging(target: any, propertyKey: string){ console.log() }

// 基本的にプロパティデコレータと引数は一緒だが、1つ追加になる // PropertyDescriptor: メソッドの中身(実行内容や設定)が入っているオブジェクト // メソッドを書き換えたりすることができる function MethodLogging(target: any, propertyKey: string, descriptor: PropertyDescriptor){ console.log(descriptor) }

@Component(“<h1></h1>”, “#app”) @Logging(“LoggingUser”) Class User{ @PropertyLogging name = “Quill”; constructor(){ console.log(“User was created!”) }

@MethodLogging greeting(){ console.log(“Hello”) } } ```