最近遇到了很多問題,真的是命運多舛。Angular真是讓人又愛又恨的框架,恨的是資料太少,遇到問題無從下手。愛的是許多其餘框架難以作到的功能,angular卻能夠輕鬆作到。javascript
話很少說,最近遇到了一箇舊項目改造的問題。拿到前同事作的頁面效果:java
第一眼就看到了這三個下拉框,按捺不住好奇心的我點了點。原來,第一個下拉框能夠選擇市屬和省屬,若是選擇市屬,那麼後面就會出現市、縣級兩個下拉框,若是是省屬,那就隱藏了,這個挺容易的。而後就是要選擇市以後,區下拉框要有對應區縣選項。emmmm,很典型的二級聯動,不過既然分析完了思路,那就開始作吧!首先呢,數據確定要從後端同事那裏拿,調用他的接口把數據填充進去。看看數據是什麼樣子的:json
數據略多,就不所有貼出來了。把實體bean建立一下,後端
Typescript code // 市級實體類 export class City { // 市級id cityId: string; // 所屬類型(0.市屬 1.省屬) cityType: number; // 市級名稱(可選屬性,若cityType爲1時,可不填) cityName: string; // 所屬區縣 counties?: Array<Country>; } // 區縣級實體類 export class Country { // 區縣id countryId: string; // 區縣名稱 countryName: string; } // 填寫市縣類 export class CityAndCountry { // 市級id cityId: string; // 縣級id countryId: string; // 市級類型 cityType: number; // 市縣級實體構造器 constructor() { // 給市級id賦予一個真實城市的id初始值 this.cityId = '***'; // 同上 this.countryId = '***'; // 同上 this.cityType = 0; } }
實體完成了,開始準備獲取數據並填充至實體:數組
Typescript code // 二級聯動組件 export class CityAreaComponent implements OnInit, OnDestroy { // 結果碼 (用於頁面處理顯示標識) result_code: number; // 市級實體聲明 city: City[]; // 縣區級實體聲明 country: Country[]; // 市縣、區級填寫實體聲明 cac: CityAndCountry; // 聲明訂閱對象 subscript: Subscription; /** * 構造器 * @param {CityService} service 注入服務 */ constructor (private service: CityService) { // 結果碼 (-1.網絡或其餘異常 0.無內容 1.請求成功 2.請等待) this.result_code = 2; // 初始化填寫市區、縣級填寫實體 cac = new CityAndCountry(); // 初始化數組(這步很重要,有不少人說使用數組相關函數會報未定義異常,是由於沒有初始化的緣由) this.city = []; this.country = []; // 初始化訂閱對象 this.subscript = new Subscription(); } /** * 生命週期初始化鉤子(生命週期儘可能按執行順序來寫,養成好習慣) */ ngOnInit(): void { this.getCityArea(); } /** 獲取市縣數據 */ getCityArea() { /** 將請求交付服務處理(service代碼比較簡單,就不貼了) */ this.subscript = this.service.getCityArea().subscribe(res => { /** 獲取json請求結果 */ const result = res.json(); /** 判斷結果返回碼 */ switch (result['code']) { /** 請求成功,而且有值 */ case 200: /** 改變初始返回碼 */ this.result_code = 1; /** 獲取並填充數據 */ this.city = json['city']; break; /** 其餘狀況不重複贅述 */ } }, err => { /** 顯示預設異常信息提示給用戶 */ this.result_code = -1; /** 打印log,儘可能使用日誌產出 */ console.error(err); }); } /** 生命週期銷燬鉤子 */ ngOnDestroy(): void { /** 取消訂閱 */ this.subscript.unsubscribe(); } }
因爲此處是單服務請求,爲了讓代碼比較清晰直觀,這裏我就不作封裝處理了。數據獲取了以後就該填充到展現界面了:網絡
Html code <!-- 所屬類型(此處固定,通常爲獲取後端數據字典數據) --> <select class="city_type" [value]="cac.cityType" [(ngModel)]="cac.cityType"> <!-- 所傳內容爲整數型 --> <option value=0>市屬</option> <option value=1>省屬</option> </select> <!-- 市級選擇(類型爲省屬時隱藏) --> <select class="city" [value]="cac.cityId" [(ngModel)]="cac.cityId" *ngIf="city.cityType==0"> <!-- 遍歷城市數組 --> <option *ngFor="let opt of option" [value]="opt.cityId">{{opt.cityName}}</option> </select>
這時候,咱們發現縣級獲取起來好像並不能直接獲取,怎麼辦呢?我忽然想到,我在ts裏面聲明一個變量獲取市級選擇的id號,而後再拿id去找下屬縣區,這樣就能夠輕鬆拿到了。既然要實時獲取變化,那咱們就實現檢測變化鉤子:框架
Typescript code // 二級聯動組件 export class CityAreaComponent implements OnInit, OnDestroy, DoCheck{ // 聲明縣區級數組 country: Array<Country>; constructor() { /** 重複代碼不贅述 */ /** 初始化數組 */ country = []; } /** 生命週期檢測變化鉤子 */ ngDoCheck(): void { /** 遍歷市級數組 */ for (let i = 0; i < this.city.length; i++) { /** 若選擇的市級id和市級數組中的id相吻合 */ if (this.city[i].id == this.cac.cityId) { /** 將該索引下的counties數組賦予給區縣級數組 */ this.country = this.city[i].counties; } /** 咱們沒法避免直轄市的狀況,因此多一重判斷 */ if (this.country.length > 0) { /** 爲了用戶體驗,咱們要儘可能在用戶選擇市級城市後,默認選擇一個區縣級城市 */ this.cac.country.id = this.country[0].id; } } } }
最後再補上區縣級下拉框:函數
Html code <!-- 區縣級下拉框 --> <select [value]="cac.countryId" [(ngModel)]="cac.countryId" *ngIf="cac.cityType==0 && country.length > 0"> <option *ngFor="let count of country" [value]="count.id">{{count.name}}</option> </select>
到此爲止,大功告成,不再用去依賴別人的庫了。工具