服务:没有Renderer2的提供者

Bee*_*ice 27 typescript angular

Angular 4.2Typescript 2.3

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

这是旧代码:

loadScript(src:string){
    const script = document.createElement('script');
    document.body.appendChild(script);
    script.src = src;
}
Run Code Online (Sandbox Code Playgroud)

现在,我想使用它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;
}
Run Code Online (Sandbox Code Playgroud)

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

错误:没有Renderer2的提供者!

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

这个plunkr证明了这个问题

Eug*_*lov 49

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

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

在Service中获取Renderer2的实例

例如,Angular在网络工作者内部使用的方式.我用下面的代码解决了这个问题:

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

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

    constructor(rendererFactory: RendererFactory2) {
        this.renderer = rendererFactory.createRenderer(null, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

@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;
  }
}
Run Code Online (Sandbox Code Playgroud)

RendererFactory2.createRenderer方法参数是:

  • hostElement 与类型 any
  • type 与类型 RendererType2|null

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

从组件传递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;
  }
}
Run Code Online (Sandbox Code Playgroud)


yur*_*zui 15

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

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

也可以看看