Angular4自制一個市縣二級聯動組件

最近遇到了很多問題,真的是命運多舛。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>

到此爲止,大功告成,不再用去依賴別人的庫了。工具

因爲沒有用IDE工具,以上代碼可能會有小缺失,如有疑問,請在評論提出。歡迎大神指點改進,謝謝!

相關文章
相關標籤/搜索