【问题标题】:How to inject Document in service?如何在服务中注入文档?
【发布时间】:2016-05-30 08:44:31
【问题描述】:

我有一个 Angular 2 应用程序。为了在测试中模拟 Document 对象,我想将它注入到服务中,例如:

import { Document } from '??' 

@Injectable()
export class MyService {
  constructor(document: Document) {}
}

Angular uses the internal getDOM() methodTitle 服务。

有没有什么简单的方法可以将Document 注入到服务中?另外,我应该如何在providers 数组中引用它?

【问题讨论】:

    标签: typescript angular


    【解决方案1】:

    Angular 已经支持了一段时间。

    您可以使用@angular/common 包提供的DOCUMENT 常量。

    DOCUMENT 常量的描述(取自API documentation):

    代表主要渲染上下文的 DI 令牌。在浏览器中,这是 DOM 文档。

    一个例子如下所示:

    我的服务.service.ts:

    import { Inject, Injectable } from '@angular/core';
    import { DOCUMENT } from '@angular/common';
    
    @Injectable()
    export class MyService {
      constructor(@Inject(DOCUMENT) private document: Document) {}
    }
    

    my-service.service.spec.ts

    import { provide } from '@angular/core';
    import { DOCUMENT } from '@angular/common';
    
    import { MyService } from './my-service';
    
    class MockDocument {}
    
    describe('MyService', () => {
      beforeEachProviders(() => ([
        provide(DOCUMENT, { useClass: MockDocument }),
        MyService
      ]));
    
      ...
    });
    

    【讨论】:

    • 而在实际实现中,我们应该提供实际的文档实例,例如,declare const document: Document;,然后是bootstrap(provide(Document, { useValue: document }));
    • @GünterZöchbauer 它看起来像DOCUMENT is deprecated。知道一旦它消失了怎么做吗?例如,如何动态设置网站图标?
    • @adamdport - 从'@angular/common'导入{文档};而不是 '@angular/platform-b​​rowser'
    • 这个答案令人困惑(它似乎无处不在 - bootstrap(provide.. 应该被调用?)。它已经过时了吗?是否有一个等效的答案实际上显示了什么是应该去哪里?请注意,我不需要模拟任何东西:我正在尝试为生产应用程序注入 DOCUMENT。另请参阅:stackoverflow.com/questions/50920734/…
    • 作为类型,你可以用HTMLDocument代替any@Inject(DOCUMENT) private document: HTMLDocument
    【解决方案2】:

    我无法直接评论 adamdport 的问题(还没有 50 个代表点),但这里是 angular 文档中所述。

    块引用 @GünterZöchbauer 看起来 DOCUMENT 已被弃用。知道一旦它消失了怎么做吗?例如,如何动态设置网站图标?

    而不是像这样从平台浏览器导入:

    import { DOCUMENT } from '@angular/platform-browser';
    

    从 angular common 导入:

    import {DOCUMENT} from '@angular/common';
    

    【讨论】:

      【解决方案3】:

      除了@Günter Zöchbauer 的回答。

      Angular 将 DOCUMENT 定义为 InjectionToken

      export const DOCUMENT = new InjectionToken<Document>('DocumentToken');
      

      dom_tokens.ts

      并将其与browser.ts中的文档一起注入

      {provide: DOCUMENT, useFactory: _document, deps: []}
      
      
      export function _document(): any {
        return document;
      }
      

      因此,我们在使用的时候,只需要注入@Inject(DOCUMENT)

      或者直接在deps:[DOCUMENT]使用token

      【讨论】:

      • 当您需要实际文档时,这适用于 AOT(生产)。它可以防止“遇到静态解析符号值时出现错误”
      • 在 AOT 中对我不起作用,至少对于 Angular 6 而言。我收到错误“无法解析所有参数...”。另见:stackoverflow.com/questions/50920734/…
      • 如果 Angular 应用程序在非浏览器中呈现,这是否正确解决?
      【解决方案4】:
      import { Inject, Injectable } from '@angular/core';
      import { DOCUMENT } from '@angular/common';
      
      @Injectable()
      export class MyService {
        constructor(@Inject(DOCUMENT) private document) {}
      }
      

      这是导致问题的“:文档”。

      【讨论】:

      • 我也遇到了同样的问题,你有解决办法吗?
      猜你喜欢
      • 1970-01-01
      • 2020-01-29
      • 2022-11-22
      • 1970-01-01
      • 2016-10-01
      • 2018-01-23
      • 2020-05-01
      • 1970-01-01
      相关资源
      最近更新 更多