如何在服务中注入文件?


78

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

import { Document } from '??' 

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

TitleAngular的服务使用内部getDOM()方法

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


我想对此表示赞成,但后来决定反对...,但感谢您提出这个问题:)
Joel Balmer

Answers:


137

Angular支持了一段时间。

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

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

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

示例如下所示:

my-service.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
  ]));

  ...
});

1
在实际的实现中,我们应该提供实际的文档实例,例如,declare const document: Document;然后bootstrap(provide(Document, { useValue: document }));
RJo,2016年

3
@GünterZöchbauer似乎已弃用DOCUMENT。知道消失后如何执行此操作吗?例如,如何动态设置图标?
adamdport

11
@adamdport-从'@ angular / common'导入{文档}; 而不是“ @ angular / platform-b​​rowser”
Tom Mettam

1
这个答案是令人困惑的(似乎到处都是-bootstrap(提供。应该在哪里叫?)。它已经过时了吗?是否有一个等效的答案实际上表明应该去哪里?不需要任何模拟:我试图注入文档生产应用程序参见:stackoverflow.com/questions/50920734/...
戴夫诺塔奇

4
作为类型,您可以使用HTMLDocument而不是any@Inject(DOCUMENT) private document: HTMLDocument
edwin

33

我无法直接对adamdport的问题发表评论(尚未提供50个代表点),但正如在角度文档中所述。

Blockquote @GünterZöchbauer似乎已弃用DOCUMENT。知道消失后如何执行此操作吗?例如,如何动态设置图标?

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

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

从通用角度导入:

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

9

除了@GünterZöchbauer的答案。

Angular将DOCUMENT定义为InjectionToken

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

dom_tokens.ts

并在浏览器中注入文档

{provide: DOCUMENT, useFactory: _document, deps: []}


export function _document(): any {
  return document;
}

因此,当我们使用它时,我们只需要注入 @Inject(DOCUMENT)

或直接在 deps:[DOCUMENT]


当您需要实际文档时,此方法可在AOT(生产)中使用。它可以防止“遇到静态错误时会解析符号值的错误”
Marcel van der Drift

在AOT中,至少在Angular 6中,它不适用于我。我收到错误消息“无法为...解析所有参数”。参见:stackoverflow.com/questions/50920734/...
戴夫诺塔奇

如果在非浏览器中渲染了角度应用程序,这可以正确解决吗?
The.Wolfgang.Grimmer

-2
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class MyService {
  constructor(@Inject(DOCUMENT) private document) {}
}

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.