angular2正式版9月15日(中秋節(jié))發(fā)布,我從10月份開始入門學(xué)習(xí)(參考前文入門日志),11月開始項(xiàng)目開發(fā),之后邊開發(fā)邊學(xué)習(xí),在此把項(xiàng)目中所遇的問題做個(gè)匯總。部分技術(shù)解決方案已經(jīng)在文集中單獨(dú)講述,總結(jié)中包含非ng2框架內(nèi)容。
1.當(dāng)頁面報(bào)錯(cuò)No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
解決方法:在index.html的header中添加<basehref='/'>
ng2官網(wǎng)中有對(duì)此作專門的講解
2.跨域
angular2項(xiàng)目中通過設(shè)置請(qǐng)求頭,或者設(shè)置攔截器,可以在請(qǐng)求header中添加access-token(身份驗(yàn)證)
1)set header方式
let headers = new Headers({ 'Content-Type': 'application/json', 'access-token': this.getToken() });
let options = new RequestOptions({ headers: headers });
return this.http.post(request_url[action], params, options)
跨域請(qǐng)求分成兩次,第一次是options請(qǐng)求,header參數(shù)在access-controller-allow-header中

這次請(qǐng)求不能被攔截,否則會(huì)報(bào)403錯(cuò)誤

第二次發(fā)出了post請(qǐng)求
有數(shù)據(jù)返回了

2)攔截器使用BaseRequestOptions
建個(gè)class繼承BaseRequestOptions
import {BaseRequestOptions} from "@angular/http";
export class MyRequestOptions extends BaseRequestOptions {
merge (options?: RequestOptionsArgs) : RequestOptions {
let headers = options.headers || new Headers;
if (!headers.get('access-token')) {
headers.append('access-token',localStorage.getItem("AccessToken"));
}
if (!headers.get('Content-Type')) {
headers.append('Content-Type','application/json');
}
options.headers = headers;
return super.merge(options);
}
}
在根模塊app.component.ts的providers中引入
import { RequestOptions } from '@angular/http';
providers : [ { provide : RequestOptions, useClass : MyRequestOptions } ]
附帶ajax中setHead方法

3.angular2中實(shí)現(xiàn)js的innerHtml或者ng1中的ng-bing-html的效果
可以通過Ng2內(nèi)置指令[innderHtml]="htmlContent"實(shí)現(xiàn),不過有個(gè)問題,htmlContent中帶有的style樣式會(huì)被過濾
解決:使用ng2的API DomSanitizer
和ng1中的 $sce.trustAsHtml()功能類似, DomSanitizer提供了bypassSecurityTrustHtml
方法,為html標(biāo)簽添加信任,避免被ng2安全機(jī)制過濾
有時(shí)候,會(huì)發(fā)現(xiàn)b、sub、sup、i等自帶樣式的標(biāo)簽沒有效果,可能是標(biāo)簽樣式被瀏覽器或者css文件重置了,通過瀏覽器開發(fā)者模式檢查一下。
4.typescript語法下,類似方法會(huì)報(bào)錯(cuò)
let a = {};
a.b = 1;
改成
a['b'] = 1;或者(a as any).b = 1;
調(diào)用window下方法
function call() {}
window.call() //運(yùn)行環(huán)境報(bào)錯(cuò)
改成
window['call'];或者(window as any).call;
(document.querySelector('.ui-paginator-first') as any).click();
還可以寫d.ts聲明文件
5.Component定義的變量,只聲明沒有初始化(后面才賦值),如果在html中用到此變量,會(huì)報(bào)錯(cuò),聲明變量的同時(shí)也要初始化。
6.表單元素中用到[(ngModel)]="name"時(shí),可以用(ngModelChange)事件監(jiān)聽變量name變化,change事件用得不好會(huì)導(dǎo)致值不實(shí)時(shí),或者代碼冗余。
關(guān)于表單的雙向綁定,后期會(huì)考慮寫一篇文章專門描述
7.Can't bind to 'ngModel' since it isn't a known property of 'input'?
需要import forms模塊到module
建議可以建一個(gè)共享模塊SharedModule,引入通用的模塊、組件,再將SharedModule引入到各個(gè)模塊中,省去麻煩,Component后指令引入到多個(gè)模塊中會(huì)報(bào)錯(cuò),也用這個(gè)方法解決。
SharedModule示例
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {CalendarModule, PaginatorModule, TreeModule, DropdownModule} from "../../assets/theme/primeng/primeng";
import { UPLOAD_DIRECTIVES } from './directives/uploader/uploader';
import { ScrollDirective } from './directives/scroll.directive';
import { DropdownPipe } from './pipe/primeng-dropdown';
import { DropdownTwoPipe } from './pipe/primeng-dropdown2';
import { SerialNumberPipe } from './pipe/serial-number1.pipe';
import { BypassSecurityTrustHtmlPipe } from './pipe/bypassSecurityTrustHtml.pipe';
import { SparkUeditorComponent } from './components/ueditor.component';
import { StarLightComponent } from './components/star-light/star-light.component';
import { PersonSelectComponent } from './components/person-select/person-select.component';
import { PersonSelectService } from './components/person-select/person-select.service';
@NgModule({
imports: [CommonModule, FormsModule,
CalendarModule, PaginatorModule, TreeModule, DropdownModule
],
exports: [CommonModule, FormsModule,UPLOAD_DIRECTIVES,
CalendarModule, PaginatorModule, TreeModule, DropdownModule,
ScrollDirective,
DropdownPipe,
DropdownTwoPipe,
SerialNumberPipe,
BypassSecurityTrustHtmlPipe,
StarLightComponent,
SparkUeditorComponent,
PersonSelectComponent
],
declarations: [
UPLOAD_DIRECTIVES,
ScrollDirective,
DropdownPipe,
DropdownTwoPipe,
SerialNumberPipe,
BypassSecurityTrustHtmlPipe,
StarLightComponent,
SparkUeditorComponent,
PersonSelectComponent
],
providers: [PersonSelectService],
})
export class ShareModule { }
8.能使用安全操作符的地方都應(yīng)該使用安全操作符,如{{user?.name}}
誰也不想看到瀏覽器報(bào)錯(cuò),頁面什么都不顯示
9.ngFor和ngIf不能在同一標(biāo)簽上使用,否則頁面報(bào)錯(cuò),可以在ngFor外層包一個(gè)標(biāo)簽,在外層標(biāo)簽中使用ngIf
10.*ngFor指令不支持鍵值對(duì){}結(jié)構(gòu)數(shù)據(jù)
解決方法:寫個(gè)管道處理數(shù)據(jù)
<div *ngFor="let obj of objs | ObjNgFor">...</div>
@Pipe({ name: 'ObjNgFor', pure: false })
export class ObjNgFor implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => value[key]);
}
}
11.ngFor獲取元素下標(biāo)
12.ngFor監(jiān)聽循環(huán)結(jié)束事件,使用指令
<div *ngFor="let item of currentUser?.frontSet;let last = last;" [isLast]="last" (lastDone)="initVav()"></div>
ngFor-isLast.ts
import { Directive, Input, Output, EventEmitter, OnInit} from "@angular/core";
@Directive({
selector : '[isLast]'
})
export class IsLastDirective implements OnInit {
@Input() isLast: boolean;
@Output() lastDone: EventEmitter<boolean> = new EventEmitter<boolean>();
ngOnInit(): void {
if (this.isLast) {
this.lastDone.emit(true);
}
}
}