typescript 服务:Renderer2 没有提供者

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44989666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 04:41:55  来源:igfitidea点击:

Service: No provider for Renderer2

angulartypescript

提问by BeetleJuice

Angular 4.2with Typescript 2.3

Angular 4.2Typescript 2.3

I am refactoring a service that is responsible for creating a new script tag and adding it to the document.

我正在重构一个负责创建新脚本标记并将其添加到文档的服务。

Here is the old code:

这是旧代码:

loadScript(src:string){
    const script = document.createElement('script');
    document.body.appendChild(script);
    script.src = src;
}

Now, I'd like to use the Renderer2to avoid doing direct DOM manipulation. So I've injected what I need in my service and updated the code:

现在,我想使用Renderer2避免进行直接的 DOM 操作。所以我在我的服务中注入了我需要的东西并更新了代码:

constructor(private renderer:Renderer2, @Inject(DOCUMENT) private document){}

loadScript(src:string){
    const script = this.renderer.createElement('script');
    this.renderer.appendChild(this.document.body,script);
    script.src = src;
}

However, I run into this error:

但是,我遇到了这个错误:

Error: no provider for Renderer2!

错误:Renderer2 没有提供程序!

The service belongs to a CoreModulewhose only import is CommonModulefrom @angular/common

该服务属于CoreModule其唯一导入CommonModule来自@angular/common

This plunkrdemonstrates the problem

这个 plunkr演示了这个问题

回答by Eugene Gavrilov

Possibly duplicating with Using Renderer in Angular 4

可能与在 Angular 4 中使用渲染器重复

You cannot inject Renderer2, but we can run RendererFactory2to get Renderer2instance inside @Injectable()service. There are two different ways of solving this issue.

您不能注入Renderer2,但我们可以运行RendererFactory2以获取服务Renderer2内的实例@Injectable()。有两种不同的方法可以解决这个问题

Get an instance of Renderer2 inside Service

在 Service 中获取 Renderer2 的实例

There is the way which Angular using internally in webworkers, for example. I've solved the problem with the code below:

例如,Angular 在 webworkers 内部使用的方式。我已经用下面的代码解决了这个问题:

import { Injectable, Renderer2, RendererFactory2 } from '@angular/core';

@Injectable()
class Service {
    private renderer: Renderer2;

    constructor(rendererFactory: RendererFactory2) {
        this.renderer = rendererFactory.createRenderer(null, null);
    }
}

In your particular case, it will be

在您的特定情况下,它将是

@Injectable()
class Service {
  private renderer: Renderer2;

  constructor(rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document){
    this.renderer = rendererFactory.createRenderer(null, null);
  }

  loadScript(src:string){
    const script = this.renderer.createElement('script');
    this.renderer.appendChild(this.document.body,script);
    script.src = src;
  }
}

Parameters of RendererFactory2.createRenderermethod are:

RendererFactory2.createRenderer方法参数为:

  • hostElementwith type any
  • typewith type RendererType2|null
  • hostElement带类型 any
  • type带类型 RendererType2|null

You can see that (null, null)parameters are here: https://github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

你可以看到(null, null)参数在这里:https: //github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

Pass Renderer2 from component

从组件传递 Renderer2

// declare public property in your service
@Injectable()
class Service {
  renderer: Renderer;
}

// pass renderer to service in your component file
class App {
  name:string;
  constructor(service: Service, renderer: Renderer2) {
      service.renderer = renderer;
  }
}

回答by yurzui

You can initialize service with an instance of Renderer2in root component

您可以使用Renderer2根组件中的实例初始化服务

@Injectable()
class MyService {
  renderer : Renderer2;
}
...
class App {
  name:string;
  constructor(service: MyService, renderer: Renderer2) {
      service.renderer = renderer;
  }
}

See also

也可以看看

回答by Florian

I tried to implement this using render2, but in a service - leading to 'StaticInjectorError(AppModule)[Renderer2]'-Error, as injecting Renderer2-Instance seems to not be possible. Solution was to inject RendererFactory2 and manullay create the reference within the service, like:

我尝试使用 render2 来实现这一点,但在服务中 - 导致 'StaticInjectorError(AppModule)[Renderer2]'-Error,因为注入 Renderer2-Instance 似乎是不可能的。解决方案是注入 RendererFactory2 和 manullay 在服务中创建引用,例如:

@Injectable({
  providedIn: 'root'
})
export class FgRendererService {
  /** Reference to render-instance */
  public renderer: Renderer2;
  /** CONSTRUCTOR */
  constructor(
    private _renderer: RendererFactory2
  ) {
    this.renderer = _renderer.createRenderer(null, null);
  }
  /** Add class to body-tag */
  addBodyClass( classToAdd: string ): void {
    this.renderer.addClass( document.body, classToAdd );
  }
  /** Remove class from body-tag */
  removeBodyClass( classToRemove: string ): void {
    this.renderer.removeClass( document.body, classToRemove );
  }
}