【问题标题】:Using service to listen for DOM events in Angular在 Angular 中使用服务监听 DOM 事件
【发布时间】:2017-06-09 20:43:13
【问题描述】:

我的 Angular 4 应用程序中有一个通用弹出组件,为了正确处理弹出显示,我需要监听 document 上的全局点击事件。

应用程序中可能同时有许多弹出组件,当用户单击这些组件之外的某个位置时,我需要关闭它们。由于显而易见的原因(应该只有一个侦听器),我不应该从组件本身绑定到 document:click 事件,所以我决定创建一个集中式服务,它将侦听文档上的全局 DOM 事件并命令弹出组件。

当弹出组件初始化时,它会向服务注册自己,而当它被销毁时,它会注销自己。因此,该服务始终具有应用程序中所有弹出组件的列表。到目前为止效果很好。

但是,我尝试将 Renderer2 注入到我的集中式服务中,以便通过它的 listen() 方法侦听 DOM 事件,但它看起来只能用于组件注入,不能用于服务注入。

另外,@HostListener('document:click') 装饰器在服务中不起作用。

我的架构正确吗?服务监听 DOM 事件是不是一个坏主意?

另一种可能的解决方案是创建另一个组件而不是服务,但我不喜欢这种方法,因为与自动创建的服务相比,它需要手动添加到应用程序的某个地方。

实现我的使用场景的最佳方式是什么?

【问题讨论】:

    标签: angular dom-events


    【解决方案1】:

    你应该使用Observable.fromEvent

    示例插件:https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5

    创建一个类似的服务:

    @Injectable()
    export class DocService {
      obs: Observable;
    
      constructor(){
        this.obs = Observable.fromEvent(document, 'click');
      }
    
      onClick(): Observable{
        return this.obs;
      }
    }
    

    然后订阅组件中的 observable:

    // here I just log the event, in your case, you close the popoup
    this.docService.onClick().subscribe(console.log, console.log);
    

    您可能需要确保点击不会在您的弹出窗口中出现。您可以处理这是您的订阅方法。

    【讨论】:

    • 这是一个有趣的方法,谢谢。但是,创建单个 DOM 侦听器然后使用 observable 将其转换为所有组件更好,还是直接在所有组件中侦听 DOM 事件是否可以接受?是否有性能考虑?
    • 如果有性能问题,那是无关紧要的。除非你有成百上千个组件。我建议使用服务,因为您只有一个事件侦听器,并且您的所有组件都可以订阅它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 2021-06-04
    • 1970-01-01
    相关资源
    最近更新 更多