如何为 Angular 组件创建自定义生命周期挂钩

问题描述 投票:0回答:1

我想为 Angular 组件创建自定义生命周期挂钩。

两个例子是我想添加基于浏览器的模糊/焦点以及浏览器上的可见性变化的钩子。 我不想向每个组件添加 @HostListener 并使用装饰器,但我不确定我是否能够访问我需要的部分。

我遇到的问题的一个例子是尝试打开/关闭有角度的材质菜单并基于新的“生命周期”挂钩。

我不确定我采取的方法是否正确。 任何其他推荐的方法意味着我不必添加 @HostListener 并在各处重复代码,我们将不胜感激。

这是我尝试使用类装饰器的堆栈闪电战。 组件引用在生命周期方法中始终为“未定义”:https://stackblitz.com/edit/angular-7oyay8?file=src/app/menu/menu.component.ts

这是组件代码:

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatMenuTrigger } from '@angular/material/menu';
import { ExtraHooks } from '../extra-hooks';

@Component({
  selector: 'app-menu',
  template: `
  <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>
  `,
  styles: [],
})
@ExtraHooks()
export class AppMenu implements ExtraHooks {
  @ViewChild(MatMenuTrigger, { static: false }) matMenuTrigger: MatMenuTrigger;

  constructor() {}

  onFocusIn() {
    console.log('focus in');
    if (this.matMenuTrigger) {
      this.matMenuTrigger.openMenu();
    }
  }

  onFocusOut() {
    console.log('focus out');
    if (this.matMenuTrigger) {
      this.matMenuTrigger.closeMenu();
    }
  }

  onViewHidden() {
    console.log('view hidden');
    if (this.matMenuTrigger) {
      this.matMenuTrigger.closeMenu();
    }
  }

  onViewVisible() {
    console.log('view visible');
    if (this.matMenuTrigger) {
      this.matMenuTrigger.openMenu();
    }
  }
}

类装饰器:

export function ExtraHooks() {
  let set = false;
  const watchVisibility = (target: ExtraHooks) => {
    // DOCUMENT VISIBILITY
    document.addEventListener('visibilitychange', function (event) {
      if (document.hidden) {
        target.onViewHidden();
      } else {
        target.onViewVisible();
      }
    });
  };

  const watchFocus = (target: ExtraHooks) => {
    window.addEventListener('focus', function (event) {
      target.onFocusIn();
    });

    window.addEventListener('blur', function (event) {
      target.onFocusOut();
    });
  };

  return function (target) {
    // MAKE SURE IT'S NOT SET MORE THAN ONCE
    if (!set) {
      watchFocus(target.prototype);
      watchVisibility(target.prototype);
      set = true;
    }
  };
}

export interface ExtraHooks {
  onFocusIn();
  onFocusOut();
  onViewVisible();
  onViewHidden();
}
angular typescript angular-material decorator
1个回答
0
投票

我写了一篇关于实现自定义生命周期挂钩的文章,我认为您可以使用那里的示例。您可以根据需要将上述会话管理器服务替换为焦点管理器服务。

https://medium.com/@r.daniel.szendrei/implementing-a-custom-lifecycle-hook-in-angular-you-probously-shouldnt-but-i-m-not-your-mum-e05e150610a6

© www.soinside.com 2019 - 2024. All rights reserved.