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