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