当用户单击下拉菜单之外的任何地方时,我想关闭我的登录菜单下拉菜单,我想使用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;
}
}
应用程序组件:
另一方面,有应用程序组件(它是下拉组件的父级):
- 该组件捕获每个click事件,并在相同的rxjs Subject(userMenu)上发出
这是代码:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
什么困扰我:
- 我对于让全局主题充当这些组件之间的连接器的想法感到非常不满意。
- 该setTimeout的:这是必要的,因为这里是,如果在此按钮,用户点击,显示的下拉什么,否则会发生:
- 用户单击按钮(不是下拉组件的一部分)以显示下拉列表。
- 显示该下拉列表,它立即订阅userMenu主题。
- 点击事件冒泡到应用程序组件并被捕获
- 应用程序组件在userMenu主题上发出事件
- 下拉组件在userMenu上捕获此操作,并隐藏下拉菜单。
- 最后,从不显示下拉列表。
这个设置的超时将订阅延迟到当前JavaScript代码回合的末尾,从而解决了问题,但是我认为这是一种非常优雅的方式。
如果您知道更清洁,更好,更智能,更快或更强大的解决方案,请告诉我:)!