跳到主要内容
版本:v6

构建错误

常见错误​

装饰器忘记加括号​

装饰器应在注释后加上括号 ()。一些示例包括:@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 知道它应该注入的参数类型,但不知道如何注入它。

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

import { MyService } from 'my-service';

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

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

@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("Host component's name: " + 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 为 undefined 不再报错
if (c) {
console.log(`Host component's name: ${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)

此错误是上面"没有提供者"错误的更具体版本。当您使用像 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 数组中。