在Angular 4中使用渲染器

22

我理解在Angular2项目中,使用渲染器而不是直接操作DOM更好。然而,即使我多次卸载、清除缓存、重新安装Node、Typescript和Angular-CLI,当我尝试注入渲染器时仍然会出现错误。

import { Injectable, Renderer2 } from '@angular/core';
constructor(private renderer: Renderer2) {}

__zone_symbol__message: "没有Renderer2的提供者!"

__zone_symbol__stack:"错误↵ 在错误.ZoneAwareError处

有人知道我做错了什么吗?


构造函数属于哪个类?是组件还是指令?还是服务? - Günter Zöchbauer
2个回答

40

更新:

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

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

这里有更多相关内容:https://github.com/angular/angular/issues/17824#issuecomment-351961146

之前的版本:

根据你的导入

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

I suspect that you're trying to inject Renderer2 in your service class. It won't work. You can't inject Renderer2 in a service. It should work for components and services that are provided within a component.
We can take a look at the source code https://github.com/angular/angular/blob/4.0.1/packages/core/src/view/provider.ts#L363-L373.
while (view) {
  if (elDef) {
    switch (tokenKey) {
      case RendererV1TokenKey: {
        const compView = findCompView(view, elDef, allowPrivateServices);
        return createRendererV1(compView);
      }
      case Renderer2TokenKey: {
        const compView = findCompView(view, elDef, allowPrivateServices);
        return compView.renderer;
      }

它仅在元素注入器树中检查。在此令牌可以提供的其他位置没有其他地方。
因此,在调用某些服务方法时,您必须从组件传递Renderer2到服务中https://github.com/angular/angular/issues/17824#issuecomment-311986129 或者您可以在组件内提供服务。
@Injectable()
export class Service {
  constructor(private r: Renderer2) {}
}
@Component({
  selector: 'my-app',
  templateUrl: `./app.component.html`,
  providers: [Service]
})
export class AppComponent { 
  constructor(private service: Service) {}
}

非常有趣 - Max Koretskyi
这个答案救了我的整个晚上。 - anysite

19
您不能注入Renderer2,但是我们可以在@Injectable()服务中运行RendererFactory2以获取Renderer2实例。例如,Angular在Web Workers内部使用的就是这种方式。
下面的代码解决了这个问题:
import { Renderer2, RendererFactory2 } from '@angular/core';

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

    constructor(rendererFactory: RendererFactory2) {
        this.renderer = rendererFactory.createRenderer(null, null);
    }
}
RendererFactory2.createRenderer 方法的参数如下:
  • hostElement 类型为 any
  • type 类型为 RendererType2|null
你可以看到这里有一个 (null, null) 参数: https://github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

@Eugene. 感谢您的回答。请问为什么 Renderer2 不能注入?因为 RendererFactory2 和 Renderer2 都是类,所以才会问。 - scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接