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:

  • 你正在导入参数的类。
  • 你已正确注释参数或指定其类型。
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 [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 数组中;如果是组件、管道或指令,则同时添加到 declarations 数组和 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.