Skip to main content

构建错误

常见错误

¥Common mistakes

忘记装饰器上的括号

¥Forgetting Parentheses on a Decorator

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

¥Decorators should have parentheses () after an annotation. Some examples include: @Injectable(), @Optional(), @Input(), etc.

@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) {}
}

常见错误

¥Common Errors

无法解析所有参数

¥Cannot Resolve all Parameters

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 知道这一点。确保:

¥This exception means that Angular is confused about one or more of the parameters for YourClass's constructor. In order to do dependency injection Angular needs to know the type of the parameter to inject. You let Angular know this by specifying the class of the parameter. Make sure:

  • 你正在导入参数的类。

    ¥You are importing the parameter's class.

  • 你已正确注释参数或指定其类型。

    ¥You have properly annotated the parameter or specified its type.

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 函数。

¥Sometimes circular references within your code can cause this error. Circular references mean that two objects depend on each other, and so there is no way to declare both of them before each other. To get around this, we can use the forwardRef function built in to Angular.



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

No provider for ParamType! (MyClass -> ParamType)

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

¥This means Angular knows the type of parameter it is supposed to inject, but it doesn't know how to inject it.

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

¥If the parameter is a service, make sure you have added the specified class to the list of providers available to your app:

import { MyService } from 'my-service';

@Component({
templateUrl: 'app/app.html',
providers: [MyService], // Don't forget me!
})
class MyApp {}

如果参数是另一个组件或指令(例如,父组件),将其添加到提供程序列表中将使错误消失,但这与上面的 提供者的多个实例 具有相同的效果。你将创建组件类的新实例,并且不会获得对所需组件实例的引用。相反,请确保你期望注入的指令或组件可用于你的组件(例如,如果你希望它是父级,那么它实际上是父级)。通过一个例子可能最容易理解:

¥If the parameter is another component or directive (for example, a parent component), adding it to your list of providers will make the error go away, but this will have the same effect as the Multiple instances of a provider above. You'll be creating a new instance of the component class, and you won't get a reference to the component instance you want. Instead, make sure that the directive or component you expect to be injected is available to your component (e.g. that it is actually a parent if you are expecting it to be a parent). This is probably easiest understood with an example:

@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 {}

下面的图表说明了可用的注入器:

¥Here's a diagram illustrating what injectors are available:

                 +-------+
| App |
+---+---+
|
+-------------+------------+
| |
+------+------+ +--------+--------+
| Div (MyDir) | | MyComp (MyDir) | <- MyComp can be injected
+-------------+ +--------+--------+
^ |
No MyComp to inject +------+------+
| P (MyDir) | <- MyComp can be injected from parent
+-------------+

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

¥To expand on the previous example, you can use the Angular @Optional annotation if you don't always expect a component/directive reference:

@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

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

当你尝试在不具有该属性的元素上绑定属性时,就会发生这种情况。如果该元素是一个组件或者具有一个或多个指令,则该组件和指令都不具有该属性。

¥This happens when you try and bind a property on an element that doesn't have that property. If the element is a component or has one or more directives on it, neither the component nor the directives have that property either.

<!-- div doesn't have a 'foo' property -->
<div [foo]="bar"></div>

没有 ControlContainer 的提供者

¥No provider for ControlContainer

No provider for ControlContainer! (NgControlName -> ControlContainer)

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

¥This error is a more specific version of the No provider error above. It happens when you use a form control like NgControlName without specifying a parent NgForm or NgFormModel. In most cases, this can be resolved by making sure your form control is within an actual form element. NgForm uses form as a selector so this will instantiate a new NgForm:

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

未找到组件工厂

¥No Component Factory Found

No component factory found for <component name>

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

¥This error happens when you are trying to use a component, provider pipe or directive that has not been imported and added to your ngModule. Whenever you add a new component, provider, pipe or directive to your app, you must add it to the ngModule in the src/app/app.module.ts file for Angular to be able to use it. To fix this error you can import the offending component, provider, pipe or directive into the app.module file and then if it is a provider add it to the providers array and for a component, pipe or directive add it to both the declarations array and entryComponents array.