当用户点击下拉菜单之外的任何地方时,我想关闭我的登录菜单下拉菜单,我想用Angular2和Angular2"方法"来实现这一点...
我已经实施了一个解决方案,但我真的对它没有信心.我认为一定有一个最简单的方法来达到同样的效果,所以如果你有任何 idea ...让我们来讨论:)!
以下是我的实现:
The dropdown component:
这是我下拉列表的组件:
- 每当该组件被设置为可见时(例如,当用户点击按钮以显示它时),它订阅存储在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;
}
}
The application component:
另一方面,还有应用程序组件(下拉组件的父组件):
- 该组件捕捉每个点击事件,并在同一个rxjs主题上发出(userMenu)
这是代码:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
What bother me:
- 我对把一个全球性的主题作为这些组成部分之间的连接点的 idea 感到不太舒服.
-
setTimeout:这是必需的,因为如果用户单击显示下拉菜单的按钮,则会发生以下情况:
- 用户单击该按钮(它不是DropDown组件的一部分)以显示下拉列表.
- 显示下拉菜单和it immediately subscribe to the userMenu subject.
- 点击事件泡沫一直到APP组件并被捕获
- 应用程序组件在userMenu主题上发出事件
- DropDown组件在userMenu上捕获此操作并隐藏该下拉菜单.
- 最后从不显示下拉列表.
这将超时延迟订阅到当前JavaScript代码的末尾,解决了这个问题,但在我看来,这是一种非常优雅的方式.
如果你知道更干净、更好、更聪明、更快或更强的解决方案,请告诉我:)!