跳到主要内容
版本:v8

构建错误

常见错误​

忘记在装饰器后添加括号​

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

@Directive({
selector: 'my-dir',
})
class MyDirective {
// 错误,应为 @Optional()
// @Optional 在此处不起作用,因此如果 parent 未定义,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("宿主组件的名称:" + 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 时会发生。在大多数情况下,可以通过确保你的表单控件在真正的表单元素内来解决。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 数组。