跳到主要内容
版本:v7

构建错误

常见错误

装饰器上忘记加括号

装饰器在注释后面应该有括号 ()。一些示例包括:@Injectable()@Optional()@Input() 等。

@Directive({
selector: 'my-dir',
})
class MyDirective {
// 错误,应该是 @Optional()
// @Optional 在这里不起作用,所以如果父级未定义,MyDirective 将出错
constructor(@Optional parent: ParentComponent) {}
}

常见错误

无法解析所有参数

Cannot resolve all parameters for 'YourClass'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'YourClass' is decorated with Injectable.

此异常意味着 Angular 对 YourClass 构造函数的一个或多个参数感到困惑。为了进行依赖注入,Angular 需要知道要注入的参数类型。您可以通过指定参数的类来让 Angular 知道这一点。请确保:

  • 您正在导入参数的类。
  • 您已正确注释参数或指定了其类型。
import { MyService } from 'my-service'; // 不要忘记导入我!

@Component({
template: `Hello World`,
})
export class MyClass {
// service 是 MyService 类型
constructor(service: MyService) {}
}

有时代码中的循环引用会导致此错误。循环引用意味着两个对象相互依赖,因此无法在彼此之前声明它们。为了解决这个问题,我们可以使用 Angular 内置的 forwardRef 函数。

import { forwardRef } from '@angular/core';

@Component({
selector: 'my-button',
template: `<div>
<icon></icon>
<input type="button" />
</div>`,
directives: [forwardRef(() => MyIcon)], // MyIcon 尚未定义
}) // forwardRef 在需要 MyIcon 时会解析它
class MyButton {
constructor() {}
}

@Directive({
selector: 'icon',
})
class MyIcon {
constructor(containerButton: MyButton) {} // MyButton 已定义
}

没有 ParamType 的提供者

No provider for ParamType! (MyClass -> ParamType)

这意味着 Angular 知道它应该注入的参数类型,但不知道如何注入它。

如果参数是一个服务,请确保已将指定的类添加到应用的 providers 列表中:

import { MyService } from 'my-service';

@Component({
templateUrl: 'app/app.html',
providers: [MyService], // 不要忘记我!
})
class MyApp {}

如果参数是另一个组件或指令(例如父组件),将它添加到 providers 列表中可以消除错误,但这将与上面的多个提供者实例产生相同的效果。您将创建一个新的组件类实例,并且无法获得所需的组件实例引用。相反,请确保您期望注入的指令或组件对您的组件可用(例如,如果您期望它是父级,那么它确实应该是父级)。通过示例可能最容易理解:

@Component({
selector: 'my-comp',
template: '<p my-dir></p>',
directives: [forwardRef(() => MyDir)],
})
class MyComp {
constructor() {
this.name = 'My Component';
}
}

@Directive({
selector: '[my-dir]',
})
class MyDir {
constructor(c: MyComp) {
// <-- 这是关键行

// 当指令在普通 div 上时会出错,因为组件树中没有 MyComp,
// 因此没有 MyComp 可以注入
console.log("宿主组件的名称:" + c.name);
}
}

@Component({
template:
'<my-comp></my-comp>' + // MyDir 构造函数中无错误,MyComp 是 MyDir 的父级
'<my-comp my-dir></my-comp>' + // MyDir 构造函数中无错误,MyComp 是 MyDir 的宿主
'<div my-dir></div>', // MyDir 构造函数中出错
directives: [MyComp, MyDir],
})
class MyApp {}

以下是可用注入器的示意图:

                 +-------+
| App |
+---+---+
|
+-------------+------------+
| |
+------+------+ +--------+--------+
| Div (MyDir) | | MyComp (MyDir) | <- MyComp 可以被注入
+-------------+ +--------+--------+
^ |
没有 MyComp 可注入 +------+------+
| P (MyDir) | <- MyComp 可以从父级注入
+-------------+

扩展前面的示例,如果您并不总是期望组件/指令引用,可以使用 Angular 的 @Optional 注释:

@Directive({
selector: '[my-dir]',
})
class MyDir {
constructor(@Optional() c: MyComp) {
// 如果 c 未定义,不再报错
if (c) {
console.log(`宿主组件的名称:${c.name}`);
}
}
}

无法绑定到 'propertyName',因为它不是已知属性

Can't bind to 'propertyName' since it isn't a known property of the 'elementName' element and there are no matching directives with a corresponding property

当您尝试绑定一个元素上没有的属性时会发生此错误。如果该元素是一个组件或包含一个或多个指令,那么该组件或指令也没有该属性。

<!-- div 没有 'foo' 属性 -->
<div [foo]="bar"></div>

没有 ControlContainer 的提供者

No provider for ControlContainer! (NgControlName -> ControlContainer)

此错误是上面 No provider 错误的更具体版本。当您使用如 NgControlName 之类的表单控件而没有指定父级 NgForm 或 NgFormModel 时就会发生。在大多数情况下,可以通过确保表单控件位于实际的 form 元素中来解决。NgForm 使用 form 作为选择器,因此这将实例化一个新的 NgForm:

@Component({
template:
'<form>' +
'<input ngControl="login">' +
'</form>'
})

未找到组件工厂

No component factory found for <component name>

当您尝试使用尚未导入并添加到 ngModule 的组件、提供者、管道或指令时,会发生此错误。每当您向应用添加新的组件、提供者、管道或指令时,必须将其添加到 src/app/app.module.ts 文件的 ngModule 中,Angular 才能使用它。要修复此错误,您可以将有问题的组件、提供者、管道或指令导入到 app.module 文件中,然后如果是提供者则添加到 providers 数组,如果是组件、管道或指令则同时添加到 declarations 数组和 entryComponents 数组。