构建错误
常见错误
忘记装饰器上的括号
装饰器应该在注解之后使用括号 ()
。一些示例包括:@Injectable()
、@Optional()
、@Input()
等等。
@Directive({
selector: 'my-dir',
})
class MyDirective {
// Wrong, should be @Optional()
// @Optional does nothing here, so MyDirective will error if parent is undefined
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'; // Don't forget to import me!
@Component({
template: `Hello World`,
})
export class MyClass {
// service is of type 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 has not been defined yet
}) // forwardRef resolves as MyIcon when MyIcon is needed
class MyButton {
constructor() {}
}
@Directive({
selector: 'icon',
})
class MyIcon {
constructor(containerButton: MyButton) {} // MyButton has been defined
}
没有为 ParamType 提供程序
No provider for ParamType! (MyClass -> ParamType)
这意味着 Angular 知道它应该注入的参数类型,但它不知道如何注入它。
如果参数是一个服务,请确保你已将指定的类添加到应用可用的提供程序列表中。
import { MyService } from 'my-service';
@Component({
templateUrl: 'app/app.html',
providers: [MyService], // Don't forget me!
})
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) {
// <-- This is the line of interest
// Errors when directive is on regular div because there is no MyComp in the
// component tree so there is no MyComp to inject
console.log("Host component's name: " + c.name);
}
}
@Component({
template:
'<my-comp></my-comp>' + // No error in MyDir constructor, MyComp is parent of MyDir
'<my-comp my-dir></my-comp>' + // No error in MyDir constructor, MyComp is host of MyDir
'<div my-dir></div>', // Errors in MyDir constructor
directives: [MyComp, MyDir],
})
class MyApp {}
以下是一个说明哪些注入器可用的图表。
+-------+
| App |
+---+---+
|
+-------------+------------+
| |
+------+------+ +--------+--------+
| Div (MyDir) | | MyComp (MyDir) | <- MyComp can be injected
+-------------+ +--------+--------+
^ |
No MyComp to inject +------+------+
| P (MyDir) | <- MyComp can be injected from parent
+-------------+
为了扩展前面的示例,如果你并不总是期望组件/指令引用,可以使用 Angular 的 @Optional
注解。
@Directive({
selector: '[my-dir]',
})
class MyDir {
constructor(@Optional() c: MyComp) {
// No longer errors if c is 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 doesn't have a 'foo' property -->
<div [foo]="bar"></div>
没有为 ControlContainer 提供程序
No provider for ControlContainer! (NgControlName -> ControlContainer)
此错误是上面 No provider
错误的更具体版本。当你在没有指定父 NgForm 或 NgFormModel 的情况下使用像 NgControlName 这样的表单控件时会发生这种情况。在大多数情况下,这可以通过确保你的表单控件在实际的表单元素中来解决。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
数组中。