从服务附加DOM事件处理程序

时间:2018-10-16 14:41:18

标签: angular typescript dom dependency-injection angular-services

当前附加DOM事件处理程序的做法是使用Renderer2.listen(),以防您不需要从模板使用它。这种方法适用于Directive s \ Component s。

如果您需要在Service中执行相同的操作,则问题是尝试将Renderer2实例注入到服务构造函数中:

export class SomeService {
    public constructor(private readonly renderer: Renderer2) {
    }
}

将导致缺少DI提供程序异常:

  

StaticInjectorError(平台:核心)[DefaultValueAccessor-> Renderer2]

为缓解这种情况,我们可以使用RendererFactory2类进行以下操作:

  

创建并初始化自定义渲染器,以实现   Renderer2基类。

但是我不确定为在服务中使用新的Render2是否是一个好的\推荐方法。

所以,问题是在服务中附加DOM事件处理程序的推荐做法是什么?

1 个答案:

答案 0 :(得分:2)

其他人评论说,此行为可能更适合ComponentDirective,但很有趣的一点是可以看到Angular中发生了什么。这是一个非常模块化的框架,这是一个很好的机会来深入了解DI。

Renderer2在服务方面有点特殊,因为它通过内部Renderer2Interceptor templates 有更多的控制权。与在根级别注入的提供程序或其他全局Angular提供程序相比,它的 scope 也有所不同:由于它用于呈现组件和指令的模板,因此仅适用于那些声明类型。 Angular使用的是一个非常低级的提供程序,用于创建带有视图的声明,因此可以将其注入到视图中-并且由于服务也是@Injectable,因此Angular DI层次结构分别处理它们,因此Renderer2在其层次结构中不可用。

使用RendererFactory是直接 Renderer2注入服务的唯一方法。

虽然我认为您对不创建另一个Renderer2实例的担心是有效的,但请查看有关the Angular repo:的评论

  

rendererFactory.createRenderer(null, null)将有所帮助,如果没有   (具体)参数传递,它将只返回默认渲染器   没有创建一个新的。 (原文如此)

因此,使用RendererFactory2.createRenderer(null, null)只会返回默认的DomRenderer。工厂可以提供创建 custom 渲染器的能力,而且值得庆幸的是,如果调用了工厂,Angular的维护良好,不会创建重复的DomRenderer

因此,只需将RendererFactory2注入服务并从中获取默认的Renderer2

也,谢谢,因为他们知道Renderer在Angular中很重要,因此努力使用它。直接参与DOM操作的人太多了。