当用户点击该下拉菜单之外的任何地方时,我想关闭我的登录菜单下拉菜单,我想用 Angular2 和 Angular2“方法”来做到这一点......
我已经实施了一个解决方案,但我真的对它没有信心。我认为必须有一种最简单的方法来实现相同的结果,所以如果您有任何想法......让我们讨论 :) !
这是我的实现:
下拉组件:
这是我的下拉列表的组件:
- 每次将此组件设置为可见时(例如:当用户单击按钮以显示它时),它都会订阅存储在SubjectsService 中的“全局”rxjs 主题userMenu。
- 每次隐藏时,它都会取消订阅此主题。
- 每次单击此组件模板内的任何位置都会触发onClick()方法,该方法只会停止事件冒泡到顶部(和应用程序组件)
这是代码
export class UserMenuComponent {
_isVisible: boolean = false;
_subscriptions: Subscription<any> = null;
constructor(public subjects: SubjectsService) {
}
onClick(event) {
event.stopPropagation();
}
set isVisible(v) {
if( v ){
setTimeout( () => {
this._subscriptions = this.subjects.userMenu.subscribe((e) => {
this.isVisible = false;
})
}, 0);
} else {
this._subscriptions.unsubscribe();
}
this._isVisible = v;
}
get isVisible() {
return this._isVisible;
}
}
应用组件:
另一方面,有应用程序组件(它是下拉组件的父级):
- 该组件捕获每个点击事件并在同一个 rxjs 主题(userMenu)上发出
这是代码:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
什么困扰我:
- 我对拥有一个全局主题作为这些组件之间的连接器的想法感到非常不舒服。
- 该setTimeout的:这是必要的,因为这里是,如果在此按钮,用户点击,显示的下拉什么,否则会发生:
- 用户单击按钮(它不是下拉组件的一部分)以显示下拉列表。
- 显示下拉菜单并立即订阅 userMenu 主题。
- 单击事件冒泡到应用程序组件并被捕获
- 应用程序组件在userMenu主题上发出一个事件
- 下拉组件在userMenu上捕获此操作并隐藏下拉列表。
- 最后,下拉菜单永远不会显示。
这个设置超时将订阅延迟到当前 JavaScript 代码轮的末尾,这解决了问题,但在我看来以一种非常优雅的方式。
如果您知道更清洁、更好、更智能、更快或更强大的解决方案,请告诉我:)!