从服务附加 DOM 事件处理程序
Attaching DOM event handler from a service
当前附加 DOM 事件处理程序的做法是使用 Renderer2.listen()
以防您需要这样做而不是从模板。这种方法适用于 Directive
s \ Component
s.
如果您需要在 Service
中执行相同的操作,问题是尝试将 Renderer2
实例注入服务构造函数:
export class SomeService {
public constructor(private readonly renderer: Renderer2) {
}
}
会导致缺少 DI 提供程序异常:
StaticInjectorError(Platform: core)[DefaultValueAccessor -> Renderer2]
为了缓解它,我们可以使用 RendererFactory2
class 来:
Creates and initializes a custom renderer that implements the
Renderer2 base class.
但我不确定为在服务中使用它而创建新的 Render2
是否是一种 good\recommended 方法。
那么,问题是在服务中附加 DOM 事件处理程序的推荐做法是什么?
其他人评论说这种行为可能更适合 Component
或 Directive
,但在较低级别上查看 Angular 中发生的事情很有趣。这是一个非常模块化的框架,这是一个了解更多关于 DI 的好机会。
Renderer2
在服务方面有点特殊,因为它通过内部 Renderer2Interceptor
对 模板 有更多控制。它的 scope 与在根级别注入的提供程序或其他全局 Angular 提供程序不同:因为它用于呈现组件和指令的模板,所以它的范围仅限于那些声明的类型。这是一个非常低级的提供者,Angular 用来创建带有视图的声明,因此它可以被注入到它们中——而且由于服务也是一个 @Injectable
,Angular DI 层次结构单独处理它们,因此 Renderer2
在它们的层次结构中不可用。
综上所述,Renderer2
在一个模块中可供 declarations
使用。但不是 providers
。 declarations
是实例,需要附加模板,但 providers
是单例,模板对他们来说意义不大。
使用 RendererFactory
是 直接 将 Renderer2
注入服务的唯一方法。
虽然我认为您对不创建 Renderer2
的另一个实例的担忧是有道理的,但请查看关于 the Angular repo:
的评论
rendererFactory.createRenderer(null, null)
would help, if no
(concrete) parameters passed, it will just return the default renderer
without create a new one. (sic)
因此,使用 RendererFactory2.createRenderer(null, null)
只会 return 默认值 DomRenderer
。工厂的存在是为了提供创建 custom 渲染器的能力,幸运的是 Angular 维护得很好,如果调用工厂就不会创建重复的 DomRenderer
.
因此,只需将 RendererFactory2
注入服务并从中获取默认值 Renderer2
。
此外,感谢您 知道 Renderer
在 Angular 中很重要,并努力使用它。直接去 DOM 操纵的人太多了。
当前附加 DOM 事件处理程序的做法是使用 Renderer2.listen()
以防您需要这样做而不是从模板。这种方法适用于 Directive
s \ Component
s.
如果您需要在 Service
中执行相同的操作,问题是尝试将 Renderer2
实例注入服务构造函数:
export class SomeService {
public constructor(private readonly renderer: Renderer2) {
}
}
会导致缺少 DI 提供程序异常:
StaticInjectorError(Platform: core)[DefaultValueAccessor -> Renderer2]
为了缓解它,我们可以使用 RendererFactory2
class 来:
Creates and initializes a custom renderer that implements the Renderer2 base class.
但我不确定为在服务中使用它而创建新的 Render2
是否是一种 good\recommended 方法。
那么,问题是在服务中附加 DOM 事件处理程序的推荐做法是什么?
其他人评论说这种行为可能更适合 Component
或 Directive
,但在较低级别上查看 Angular 中发生的事情很有趣。这是一个非常模块化的框架,这是一个了解更多关于 DI 的好机会。
Renderer2
在服务方面有点特殊,因为它通过内部 Renderer2Interceptor
对 模板 有更多控制。它的 scope 与在根级别注入的提供程序或其他全局 Angular 提供程序不同:因为它用于呈现组件和指令的模板,所以它的范围仅限于那些声明的类型。这是一个非常低级的提供者,Angular 用来创建带有视图的声明,因此它可以被注入到它们中——而且由于服务也是一个 @Injectable
,Angular DI 层次结构单独处理它们,因此 Renderer2
在它们的层次结构中不可用。
综上所述,Renderer2
在一个模块中可供 declarations
使用。但不是 providers
。 declarations
是实例,需要附加模板,但 providers
是单例,模板对他们来说意义不大。
使用 RendererFactory
是 直接 将 Renderer2
注入服务的唯一方法。
虽然我认为您对不创建 Renderer2
的另一个实例的担忧是有道理的,但请查看关于 the Angular repo:
rendererFactory.createRenderer(null, null)
would help, if no (concrete) parameters passed, it will just return the default renderer without create a new one. (sic)
因此,使用 RendererFactory2.createRenderer(null, null)
只会 return 默认值 DomRenderer
。工厂的存在是为了提供创建 custom 渲染器的能力,幸运的是 Angular 维护得很好,如果调用工厂就不会创建重复的 DomRenderer
.
因此,只需将 RendererFactory2
注入服务并从中获取默认值 Renderer2
。
此外,感谢您 知道 Renderer
在 Angular 中很重要,并努力使用它。直接去 DOM 操纵的人太多了。