programing

서비스:렌더러2에 대한 공급자 없음

bestprogram 2023. 8. 20. 12:19

서비스:렌더러2에 대한 공급자 없음

Angular 4.2와 함께Typescript 2.3

새로운 스크립트 태그를 생성하여 문서에 추가하는 서비스를 리팩터링하고 있습니다.

이전 코드는 다음과 같습니다.

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

이제, 저는 그것을 사용하고 싶습니다.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;
}

그러나 다음 오류가 발생합니다.

오류: 렌더러2에 대한 공급자가 없습니다!

서비스는 다음에 속합니다.CoreModule그의 유일한 중요한 것인.CommonModule부터@angular/common

이 플런커는 문제를 보여줍니다.

Angular 4에서 렌더러를 사용하여 복제 가능성

주입할 수 없습니다.Renderer2하지만 우리는 달릴 수 있습니다.RendererFactory2갖기 위해Renderer2내부의 예@Injectable()서비스. 문제를 해결하는 데는 두 가지 다른 방법이 있습니다.

서비스 내부의 렌더러2 인스턴스를 가져옵니다.

예를 들어 Angular가 웹 워커에서 내부적으로 사용하는 방식이 있습니다.아래 코드의 문제를 해결했습니다.

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

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

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

당신의 특별한 경우, 그것입니다.

@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;
  }
}

매개 변수:RendererFactory2.createRenderer방법:

  • hostElement활자로any
  • type활자로RendererType2|null

보다시피(null, null)매개 변수는 다음과 같습니다. https://github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

구성 요소에서 렌더러2 전달

// 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;
  }
}

의 인스턴스를 사용하여 서비스를 초기화할 수 있습니다.Renderer2근본 성분으로

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

참고 항목

render2를 사용하여 이를 구현하려고 했지만 서비스에서 'StaticInjectorError(AppModule)'가 발생했습니다.[Renderer2]-오류입니다. 렌더러2-Instance를 주입할 수 없습니다.솔루션은 RendererFactory2를 주입하고 manelay를 통해 다음과 같은 참조를 서비스 내에 생성하는 것이었습니다.

@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 );
  }
}

중요 참고:

고객의 요구사항에 적합한 접근 방식을 선택하는 것이 중요합니다.Renderer2다양한 구현 가능DefaultDomRenderer2,BaseAnimationRenderer,DebugRenderer2,EmulatedEncapsulationDomRenderer2예를 들어 View Encapsulation을 사용하는 각 구성 요소는 서로 다른 렌더러를 가져옵니다.

형제 구성 요소에서 제공하는 서비스에 렌더러2를 주입하면 해당 구성 요소의 렌더러가 자동으로 제공됩니다.이는 View Encapsulation에 중요합니다. 렌더링업체가 실제로 이러한 기능을 생성하는 방법을 알고 있기 때문입니다._ngcontent-appName-c339스타일 범위를 지정할 수 있습니다.

주사를 놓으면Renderer2루트 레벨에서, 조상 구성 요소 또는 당신의AppComponent그런 다음 HTML을 생성하는 데 사용하려고 하면 호스트 속성이 없거나 잘못된 속성이 더 심해질 것입니다.

SSR 또는 웹 작업자를 사용하는 경우에도 기대 사항을 신중하게 테스트해야 합니다.

이 중 어느 것도 당신이 하고 있는 일에 중요하지 않을 수 있지만, 다른 사례가 있는 이유를 아는 것이 중요합니다.Renderer2.

언급URL : https://stackoverflow.com/questions/44989666/service-no-provider-for-renderer2