EventEmitter實(shí)現(xiàn)自定義事件
通常,指令使用 Angular EventEmitter 來觸發(fā)自定義事件。 指令創(chuàng)建一個(gè)EventEmitter實(shí)例,并且把它作為屬性暴露出來。 指令調(diào)用EventEmitter.emit(payload)來觸發(fā)事件
deleteRequest = new [EventEmitter](https://angular.cn/api/core/EventEmitter)<Hero>();
delete() {
this.deleteRequest.emit(this.hero);
}
模板表達(dá)式操作符
管道操作符 ( | )
<div>Title through uppercase pipe: {{title | uppercase}}</div>
安全導(dǎo)航操作符 ( ?. ) 和空屬性路徑
Angular 的安全導(dǎo)航操作符 (?.) 是一種流暢而便利的方式,用來保護(hù)出現(xiàn)在屬性路徑中 null 和 undefined 值。 下例中,當(dāng)currentHero為空時(shí),保護(hù)視圖渲染器,讓它免于失敗。
<span>{{currentClasses?.colorC}}</span>
加上安全操作符 ?. 后,如果currentClasses對(duì)象沒有colorC屬性時(shí),span標(biāo)簽里沒有內(nèi)容,也不會(huì)報(bào)錯(cuò)。
常見問題
1.date
'Missing locale data for the locale "fr".' for pipe 'DatePipe'
import{ registerLocaleData} from '@angular/common';
import localeFr from '@angular/common/locales/fr';
registerLocaleData(localeFr, 'fr');
[<u>https://angular.cn/guide/i18n</u>](https://angular.cn/guide/i18n)
2. post請(qǐng)求請(qǐng)求頭報(bào)錯(cuò)
Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers
private headers= new Headers({'Content-Type': 'application/json'});
對(duì)于跨域請(qǐng)求,將內(nèi)容類型設(shè)置為應(yīng)用程序/x-www-form- urlencoding、multipart/form-data或text/plain之外的任何內(nèi)容類型,都會(huì)觸發(fā)瀏覽器向服務(wù)器發(fā)送飛行前選項(xiàng)請(qǐng)求。
因此,盡管服務(wù)器允許跨源請(qǐng)求,但不允許訪問控制允許頭文件,它將拋出錯(cuò)誤。默認(rèn)情況下,angular的內(nèi)容類型是application/json,它試圖發(fā)送一個(gè)選項(xiàng)請(qǐng)求。嘗試在服務(wù)器端覆蓋angular默認(rèn)的標(biāo)頭或允許訪問控制允許標(biāo)頭。下面是一個(gè)angular示例:
private headers= new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
-
ngFor報(bào)錯(cuò)
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays
this.myStock= this.quoSer.loadStockBaseMsg(list, 1, 'zd,zdf')
.subscribe(res => {
console.log(res);
this.myStock= res;
});
去掉 this.nyStock =就可以了
this.quoSer.loadStockBaseMsg(list, 1, 'zd,zdf')
.subscribe(res => {
console.log(res);
this.myStock= res;
});
- 運(yùn)行項(xiàng)目不能自動(dòng)打開瀏覽器
運(yùn)行命令:ng serve --open即可
-
新建項(xiàng)目報(bào)錯(cuò)
Schematic input does not validate against the Schema: {"name":"angular_ng","version":"6.1.3","newProjectRoot":"projects","skipInstall":false,"linkCli":false,"skipGit":false,"commit":null} Errors:Data path ".name" should match format "html-selector".
項(xiàng)目名稱格式不對(duì),改一下項(xiàng)目名稱就解決了。
6.語言切換主菜單不改變問題
app.component.html
在引用的地方加上打開關(guān)閉主菜單的監(jiān)聽函數(shù)(ionWillOpen)="menuOpen()" (ionDidClose)="menuClose()"
<ion-menu type="push" (ionWillOpen)="menuOpen()" (ionDidClose)="menuClose()">
<ion-header>
<ion-toolbar>
<ion-title i18n="菜單|app">菜單</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<app-main-menu [itemActive]="currLoc" [menuStatus]="isOpen"></app-main-menu>
</ion-content>
</ion-menu>
menuOpen() {
this.isOpen= true;
}
menuClose() {
this.isOpen= false;
}
打開菜單,關(guān)閉菜單時(shí)改變變量isOpen,用來標(biāo)記當(dāng)前菜單狀態(tài);
把變量isOpen傳遞給主菜單組件
<app-main-menu [menuStatus]="isOpen"></app-main-menu>
在子組件接收菜單狀態(tài)
@Input()
set menuStatus(val:boolean) {
this.isOpen= val;
if(val) {
this.translate.setDefaultLang(this.setting.getSettings().lang);
}
}
get menuStatus() {return this.isOpen;}
當(dāng)收到菜單為打開時(shí),就去設(shè)置語言,這樣就解決了。

7.頁面銷毀事件不執(zhí)行問題
html跳轉(zhuǎn)的路由‘routerDirection’賦值為‘root’可以解決;
[routerDirection]="'root'"
js跳轉(zhuǎn):
import{ AlertController, ToastController, ModalController, NavController} from '@ionic/angular';
nav: NavController
this.nav.navigateRoot('/users/firstSet');
測(cè)試報(bào)錯(cuò)
1. location
angular NullInjectorError: No provider for Location
報(bào)著個(gè)錯(cuò)是因?yàn)閟pec.ts文件里沒有導(dǎo)入Location,需要導(dǎo)入:
import {Location } from '@angular/common';
providers注入
providers: [
Location,
...
]
之后在測(cè)試,如果又出現(xiàn)新的報(bào)錯(cuò) angular NullInjectorError: No provider for LocationStrategy
則需要繼續(xù)導(dǎo)入LocationStrategy:
import {Location ,LocationStrategy} from '@angular/common';
providers注入
providers: [
Location,
{ provide: LocationStrategy, useClass:PathLocationStrategy },
...
]
繼續(xù)運(yùn)行測(cè)試可能還會(huì)出現(xiàn)以下報(bào)錯(cuò)
TypeError: this._platformStrategy.getBaseHref is not a function
還需繼續(xù)導(dǎo)入PathLocationStrategy, APP_BASE_HREF
import {Location ,LocationStrategy, PathLocationStrategy, APP_BASE_HREF} from '@angular/common';
providers: [
Location,
{ provide: LocationStrategy, useClass:PathLocationStrategy },
{ provide: APP_BASE_HREF, useValue: '/my/app'}
...
]
2. NavParams
報(bào)錯(cuò): Can't resolve all parameters for NavParams: (?) (ionic)
解決:
在測(cè)試文件里添加
providers: [
{ provide: NavParams, useClass: class{ NavParams= jasmine.createSpy('NavParams'); }},
{ provide: NavParams, useValue:{ data:{ 'MYVALUE': 'XYZ'}}}
]
3. post\get請(qǐng)求JSON報(bào)錯(cuò)問題
Unexpected end of JSON input in ...
this.http.post(loc, JSON.stringify(pm), {headers: this.headers}).pipe(
map(res => {
res.json();
})
)
.subscribe(res => {
this.quotesContext.session= res.data.session;
}, err => {
console.error('登錄jybData失敗:', err);
});
如果res為空/未定義/空字符串,您將得到錯(cuò)誤。在使用res.json()之前,只需檢查res的值,就不會(huì)得到錯(cuò)誤。為了確保這一點(diǎn),在嘗試解析它之前先創(chuàng)建一個(gè)console.log(res)。
參照如下修改就不會(huì)報(bào)錯(cuò):
map(res => {
if (res) {
return res.json();
}
})
4. 表單報(bào)錯(cuò)
1.No value accessor for form control with name: 'name'
<ion-range [(ngModel)]="buyFund" (ionBlur)="fundSelected()" pin="true" min="0" [max]="maxbuy" name="name" [ngModelOptions]="{standalone: true}" color="danger"></ion-range>
只需要添加上ngDefaultControl屬性即可
<ion-range [(ngModel)]="buyFund" (ionBlur)="fundSelected()" pin="true" min="0" [max]="maxbuy" name="name" [ngModelOptions]="{standalone: true}" color="danger" ngDefaultControl></ion-range>
2.Can't bind to 'formGroup' since it isn't a known property of 'form'.
在使用form表單時(shí),如果用到了form-group與formControlName,需要在app.module.ts中的import引入的不僅僅有FormsModule,還要引入ReactiveFormsModule。
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
@NgModule({
imports: [
FormsModule,
ReactiveFormsModule
]
})
5. platform
this.platform.is is not a function
測(cè)試文件:
import{ Platform, AlertController, ToastController} from '@ionic/angular';
beforeEach(async() => {
platformReadySpy= Promise.resolve();
platformSpy= jasmine.createSpyObj('Platform', { ready: platformReadySpy,is:()=> {} });
TestBed.configureTestingModule({
providers: [
{ provide: Platform, useValue: platformSpy },
],
}).compileComponents();
});
6.The pipe 'translate' could not be found
import{ TranslateModule} from '@ngx-translate/core';
imports: [TranslateModule.forRoot()]
7.ERROR in node_modules/@biesbjerg/ngx-translate-extract/dist/cli/cli.d.ts(1,23): error TS2688: Cannot find type definition file for 'yargs'
多語言翻譯文件引用地址錯(cuò)誤
import{ _} from '@biesbjerg/ngx-translate-extract';
改為一下引用地址即可:
import{ _} from '@biesbjerg/ngx-translate-extract/dist/utils/utils';
8. ERROR Error: ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked. Previous value: 'model: undefined'. Current value: 'model: false'.
原因:Angular通過修補(bǔ)一些異步api(如addEventHandler、setTimeout等)來知道事件何時(shí)被完全處理,然后在每個(gè)事件之后運(yùn)行變更檢測(cè)。
在開發(fā)模式下,Angular會(huì)在第一個(gè)變更檢測(cè)之后執(zhí)行一個(gè)額外的變更檢測(cè)。因?yàn)橹虚g沒有事件,所以不應(yīng)該發(fā)生任何變化。如果模型仍然改變,Angular認(rèn)為這是一個(gè)可能的bug。
在開發(fā)模式中,更改檢測(cè)將第二次運(yùn)行,并將當(dāng)前值與第一次運(yùn)行進(jìn)行比較。 如果值不同,那么它“認(rèn)為”更改是由它自己引起的。這就是它拋出的原因。但是,在enableProdMode()的生產(chǎn)模式中不會(huì)發(fā)生這種情況。
解決方法:
在main.ts里添加
import { enableProdMode } from '@angular/core';
enableProdMode();
- cookie
儲(chǔ)存cookie
this.cookieService.set("userId",this.userId,new Date(new Date().getTime() + this.time));
this.cookieService.set("userName",response.data.name,new Date(new Date().getTime() + this.time));
讀取cookie
this.cookieService.get("userId");
this.cookieService.get("userName");
重新存儲(chǔ)cookie
this.cookieService.set("userId",this.cookieService.get("userId"),new Date(new Date().getTime() + this.time));
this.cookieService.set("userName",this.cookieService.get("userName"),new Date(new Date().getTime() + this.time));
刪除cookie
this.cookieService.delete("userId");
check( name: string ): boolean;
get( name: string ): string;
set( name: string, value: string, expires?: number | Date, path?: string, domain?: string, secure?: boolean, sameSite?: 'Lax' | 'Strict' ): void;
delete( name: string, path?: string, domain?: string ): void;
deleteAll( path?: string, domain?: string ): void;
8.共享模塊
項(xiàng)目中分有多個(gè)模塊(Module),當(dāng)兩個(gè)或多個(gè)模塊都引用同一個(gè)服務(wù)、管道等組件時(shí),angular編譯會(huì)報(bào)錯(cuò),這種情況需要新創(chuàng)建一個(gè)共享模塊,來承載共用組件;


如上圖所示,項(xiàng)目quotes模塊和trade模塊都引入了xpipes.ts里的adata管道,如果在quotes.Moudle和tradeModule里直接引用AdataPipe就會(huì)報(bào)錯(cuò),所以新建一個(gè)共享模塊(ng g module share),在share.module.ts里引入共用的管道
share.module.ts:
import{ NgModule} from '@angular/core';
import{ CommonModule} from '@angular/common';
import { AdataPipe, LimitToPipe} from '../components/pipes/xpipes';
@NgModule({
imports: [
CommonModule
],
declarations: [
AdataPipe,
LimitToPipe
],
exports: [
AdataPipe,
LimitToPipe
]
})
export class ShareModule { }
然后再把shareModule引入到兩個(gè)用到管道的模塊里:


這樣就可以在quotes.Moudle和tradeModule這兩個(gè)模塊下的組件里用shareModule導(dǎo)出的管道了;(這里舉例是管道,服務(wù)等其他共用都參照這種做法);
9.移動(dòng)端點(diǎn)擊事件監(jiān)聽
(touchstart)="addColor()" (touchend)="removeColor()"
相當(dāng)于電腦網(wǎng)頁的keydown、keyup事件