W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
以下是你可能會遇到的元數(shù)據(jù)錯誤,帶有解釋和建議的更正。
編譯器在對 Angular 元數(shù)據(jù)求值時遇到了一個它不能理解的表達式。
如以下范例所示,使用了編譯器的受限表達式語法之外的語言特性可能會產(chǎn)生此錯誤:
// ERROR
export class Fooish { … }
…
const prop = typeof Fooish; // typeof is not valid in metadata
…
// bracket notation is not valid in metadata
{ provide: 'token', useValue: { [prop]: 'value' } };
…
你可以在普通的應用代碼中使用 ?typeof
?和方括號標記法來指定屬性名,但是這些特性不能在定義 Angular 元數(shù)據(jù)的表達式中使用。
通過在編寫 Angular 元數(shù)據(jù)時堅持使用編譯器的受限表達式語法來避免此錯誤,并小心新的或不常用的 TypeScript 功能。
如果要引用局部(未導出的)符號 'symbol name',請考慮導出它。
編譯器遇到了局部定義的未導出或未初始化的符號。
下面就是存在該問題的 ?provider
?范例。
// ERROR
let foo: number; // neither exported nor initialized
@Component({
selector: 'my-component',
template: … ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
編譯器會生成這個組件工廠,其中包含 ?useValue
?提供者的代碼。那個工廠模塊不能訪問這個源碼模塊,無法訪問這個(未導出的)?foo
?變量。
你可以通過初始化 ?foo
?來修正這個錯誤。
let foo = 42; // initialized
編譯器會將表達式折疊到提供者中,就像你自己寫的一樣。
providers: [
{ provide: Foo, useValue: 42 }
]
另外,你也可以通過導出 ?foo
?來解決它,這樣 ?foo
?將會在運行期間你真正知道它的值的時候被賦值。
// CORRECTED
export let foo: number; // exported
@Component({
selector: 'my-component',
template: … ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
添加 ?export
?的方式通常用于需要在元數(shù)據(jù)中引用變量時,如 ?providers
?和 ?animations
?,這樣編譯器就可以在這些表達式中生成對已導出變量的引用了。它不需要知道這些變量的值。
當編譯器需要知道真正的值以生成代碼時,添加 ?export
?的方式就是無效的。比如這里的 ?template
?屬性。
// ERROR
export let someTemplate: string; // exported but not initialized
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
編譯器現(xiàn)在就需要 ?template
?屬性的值來生成組件工廠。 僅僅有對該變量的引用是不夠的。 給這個聲明加上 ?export
?前綴只會生成一個新的錯誤 "?Only initialized variables and constants can be referenced
?【只能引用初始化過的變量和常量】"。
只能引用已初始化過的變量和常量,因為模板編譯器需要該變量的值。
編譯器發(fā)現(xiàn)某個到已導出的變量或靜態(tài)字段的引用是沒有初始化過的。而它需要根據(jù)那個變量的值來生成代碼。
下面的例子試圖把組件的 ?template
?屬性設置為已導出的 ?someTemplate
?變量的值,而這個值雖然聲明過,卻沒有初始化過。
// ERROR
export let someTemplate: string;
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
如果你從其它模塊中導入了 ?someTemplate
?,但那個模塊中忘了初始化它,就會看到這個錯誤。
// ERROR - not initialized there either
import { someTemplate } from './config';
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
編譯器不能等到運行時才得到該模板的信息。它必須從源碼中靜態(tài)獲得這個 ?someTemplate
?變量的值,以便生成組件工廠,組件工廠中需要包含根據(jù)這個模板來生成元素的代碼。
要糾正這個錯誤,請在同一行的初始化子句中初始化這個變量的值。
// CORRECTED
export let someTemplate = '<h1>Greetings from Angular</h1>';
@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
對非導出類 ?
<class name>
? 的引用。 考慮導出此類。
元數(shù)據(jù)引用了一個未導出的類。
比如,你可能定義了一個類并在某個 ?providers
?數(shù)組中把它用作了依賴注入令牌,但是忘了導出這個類。
// ERROR
abstract class MyStrategy { }
…
providers: [
{ provide: MyStrategy, useValue: … }
]
…
Angular 在單獨的模塊中生成類工廠,并且該工廠只能訪問導出的類。要更正此錯誤,請導出所引用的類。
// CORRECTED
export abstract class MyStrategy { }
…
providers: [
{ provide: MyStrategy, useValue: … }
]
…
元數(shù)據(jù)中引用了未導出的函數(shù)。
比如,你可能已經(jīng)把某個服務提供者的 ?useFactory
?屬性設置成了一個局部定義但忘了導出的函數(shù)。
// ERROR
function myStrategy() { … }
…
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
…
Angular 在單獨的模塊中生成類工廠,該工廠只能訪問導出的函數(shù)。要更正此錯誤,請導出此函數(shù)。
// CORRECTED
export function myStrategy() { … }
…
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
…
不支持函數(shù)調(diào)用。考慮把這個函數(shù)或 lambda 表達式替換成一個對已導出函數(shù)的引用。
編譯器當前不支持函數(shù)表達式或 lambda 函數(shù)。比如,你不能將提供者的 ?useFactory
?設置為這樣的匿名函數(shù)或箭頭函數(shù)。
// ERROR
…
providers: [
{ provide: MyStrategy, useFactory: function() { … } },
{ provide: OtherStrategy, useFactory: () => { … } }
]
…
如果你在某個提供者的 ?useValue
?中調(diào)用函數(shù)或方法,也會導致這個錯誤。
// ERROR
import { calculateValue } from './utilities';
…
providers: [
{ provide: SomeValue, useValue: calculateValue() }
]
…
要改正這個問題,就要從模塊中導出這個函數(shù),并改成在服務提供者的 ?useFactory
?中引用該函數(shù)。
// CORRECTED
import { calculateValue } from './utilities';
export function myStrategy() { … }
export function otherStrategy() { … }
export function someValueFactory() {
return calculateValue();
}
…
providers: [
{ provide: MyStrategy, useFactory: myStrategy },
{ provide: OtherStrategy, useFactory: otherStrategy },
{ provide: SomeValue, useFactory: someValueFactory }
]
…
模板編譯器不支持引用導出的解構語法的變量或常量。考慮簡化這一點,以避免解構語法。
編譯器不支持引用通過解構賦值的方式得到的變量。
比如,你不能這么寫:
// ERROR
import { configuration } from './configuration';
// destructured assignment to foo and bar
const {foo, bar} = configuration;
…
providers: [
{provide: Foo, useValue: foo},
{provide: Bar, useValue: bar},
]
…
要糾正這個錯誤,就要引用非解構方式的變量。
// CORRECTED
import { configuration } from './configuration';
…
providers: [
{provide: Foo, useValue: configuration.foo},
{provide: Bar, useValue: configuration.bar},
]
…
編譯器遇到了某個類型,但是不知道它是由哪個模塊導出的。
這通常會發(fā)生在你引用環(huán)境類型時。比如,?Window
?類型就是在全局 ?.d.ts
? 文件中聲明的環(huán)境類型。
如果你在組件的構造函數(shù)中引用它就會導致一個錯誤,因為編譯器必須對構造函數(shù)進行靜態(tài)分析。
// ERROR
@Component({ })
export class MyComponent {
constructor (private win: Window) { … }
}
TypeScript 能理解這些環(huán)境類型,所以你不用導入它們。但 Angular 編譯器不理解你沒有導入或?qū)С鲞^的類型。
這種情況下,編譯器就無法理解如何使用這個 ?Window
?令牌來進行注入。
不要在元數(shù)據(jù)表達式中引用環(huán)境類型。
如果你必須注入某個環(huán)境類型的實例,可以用以下四步來巧妙解決這個問題:
useFactory
?提供者。
@Inject
? 來注入這個實例。下面的例子說明了這一點。
// CORRECTED
import { Inject } from '@angular/core';
export const WINDOW = new InjectionToken('Window');
export function _window() { return window; }
@Component({
…
providers: [
{ provide: WINDOW, useFactory: _window }
]
})
export class MyComponent {
constructor (@Inject(WINDOW) private win: Window) { … }
}
對于編譯器來說,構造函數(shù)中出現(xiàn) ?Window
? 類型已不再是個問題,因為它現(xiàn)在使用 ?@Inject(WINDOW)
? 來生成注入代碼。
Angular 也用 ?DOCUMENT
?令牌做了類似的事情,所以你也可以注入瀏覽器的 ?document
?對象(或它的一個抽象層,取決于該應用運行在哪個平臺)。
import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Component({ … })
export class MyComponent {
constructor (@Inject(DOCUMENT) private doc: Document) { … }
}
編譯器在正在計算的表達式中期望有一個名字。
如果將數(shù)字用作屬性名稱,則可能發(fā)生這種情況,如以下范例所示。
// ERROR
provider: [{ provide: Foo, useValue: { 0: 'test' } }]
把該屬性的名字改為非數(shù)字類型。
// CORRECTED
provider: [{ provide: Foo, useValue: { '0': 'test' } }]
Angular 不能確定你在元數(shù)據(jù)中引用的枚舉成員的值。
編譯器可以理解簡單的枚舉值,但不能理解復雜的,比如從那些計算屬性中派生出來的。
// ERROR
enum Colors {
Red = 1,
White,
Blue = "Blue".length // computed
}
…
providers: [
{ provide: BaseColor, useValue: Colors.White } // ok
{ provide: DangerColor, useValue: Colors.Red } // ok
{ provide: StrongColor, useValue: Colors.Blue } // bad
]
…
避免引用那些使用了復雜初始化對象或計算屬性的枚舉。
元數(shù)據(jù)中不支持帶標簽函數(shù)的模板表達式。
編譯器遇到了 JavaScript ES2015 帶標簽的模板表達式,如下所示。
// ERROR
const expression = 'funky';
const raw = String.raw`A tagged template ${expression} string`;
…
template: '<div>' + raw + '</div>'
…
String.raw()是 JavaScript ES2015 的原生標簽函數(shù)。
AOT 編譯器不支持帶標簽函數(shù)的模板表達式,避免在元數(shù)據(jù)表達式中使用它們。
編譯器期待在錯誤信息指出的位置是一個符號引用。
當你在類的 ?extends
?子句中使用表達式時就會出現(xiàn)這個錯誤。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: