前言
最近在寫(xiě)一個(gè)項(xiàng)目,其中用到省市區(qū)的三級(jí)聯(lián)動(dòng)組件。起初,由于時(shí)間緊湊,使用的是第三方的一個(gè)聯(lián)動(dòng)組件。但是,回過(guò)頭來(lái)發(fā)現(xiàn),整個(gè)組件的風(fēng)格與整個(gè)網(wǎng)站的material風(fēng)格不相符合,心里難受,就自己動(dòng)手寫(xiě)了這么一個(gè)組件,該組件是建立在Google的angular material2的基礎(chǔ)之上進(jìn)行編寫(xiě)的,下面我將記錄編寫(xiě)的整個(gè)流程。
組件效果圖
組件分析
1.需要配置@angular/material,配置的問(wèn)題本文不做具體的講述,可以訪問(wèn)下面的鏈接進(jìn)行配置點(diǎn)擊此處(需要翻X)
組件會(huì)使用到angular material中的MdSelectModule,所以需要導(dǎo)入MdSelectModule
2.省市區(qū)數(shù)據(jù)的來(lái)源,其實(shí)網(wǎng)上有許多json的數(shù)據(jù)源,而且這些數(shù)據(jù)源大致都是雷同的,所以我就直接從網(wǎng)上扒下一組比較好處理的json數(shù)據(jù)源,數(shù)據(jù)源放在我的服務(wù)器上數(shù)據(jù)源(直接訪問(wèn)的話,可能瀏覽器編碼需要改一下,也可以直接去瀏覽器后臺(tái)抓取文件)
3.數(shù)據(jù)搞定之后,就來(lái)看一下組件的代碼部分
- three-link.service.ts代碼部分
import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Rx';
const ThreeLinkUrl = 'src/mock-data/three-link.json';
@Injectable()
export class ThreeLinkService {
constructor(public _http: Http) {
}
public setAll() { //獲取json中的數(shù)據(jù)
return this._http.get(ThreeLinkUrl)
.map((response: Response) => {
const res = response.json();
return res;
})
.catch((error: any) => Observable.throw('Server error' || error));
}
}
這里我請(qǐng)求了存放在mock-data文件夾中的three-link.json文件,使用的是rxjs的方法。之后的component中將調(diào)用服務(wù)的setAll()函數(shù)
- three-link.component.ts代碼部分
mport {Component, OnInit} from '@angular/core';
import {ThreeLinkService} from './three-link.service';
@Component({
selector: 'app-three-link',
templateUrl: './three-link.html',
styleUrls: ['./three-link.css']
})
export class ThreeLinkComponent implements OnInit {
public all: Array<object>; //存儲(chǔ)所有的省市區(qū)數(shù)據(jù)
public provinces: Array<object>; //存儲(chǔ)省的信息
public citys: Array<object>; //存儲(chǔ)城市的信息
public areas: Array<object>; //存儲(chǔ)地區(qū)的信息
public cityValue: string; //重置城市選擇器時(shí)用到的變量
public areaValue: string; //重置地區(qū)選擇器時(shí)用到的變量
constructor(public threeLinkService: ThreeLinkService) {
}
ngOnInit() {
this.setAll();
}
private setAll() {
this.threeLinkService.setAll()
.subscribe(
data => {
this.all = data;
this.provinces = this.setProvinces();
},
error => {
console.log(error);
}
);
}
private setProvinces() {
if (this.all !== undefined ) {
const result = new Array<object>();
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'].slice(2, 6) === '0000') {
result.push(value);
}
}
return result;
}
}
private setCity(province: string) {
if (this.all !== undefined) {
const result = new Array();
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'].slice(0, 2) === province.slice(0, 2)
&& value['item_code'] !== province && value['item_code'].slice(4, 6) === '00') {
result.push(value);
}
}
return result;
}
}
private setArea(city: string) {
if (this.all !== undefined) {
const result = [];
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'] !== city && value['item_code'].slice(0, 4) === city.slice(0, 4)) {
result.push(value);
}
}
return result;
}
}
public selectProvince(code: string) {
this.cityValue = 'undefined';
this.areaValue = 'undefined';
this.citys = this.setCity(code);
}
public selectCity(code: string) {
this.areaValue = 'undefined';
this.areas = this.setArea(code);
}
}
整個(gè)代碼段沒(méi)必要全部看完,我們可以分成3個(gè)部分來(lái)進(jìn)行分析
1.第一部分(初始化省信息部分)
private setAll() {
this.threeLinkService.setAll()
.subscribe(
data => {
this.all = data; //將獲取的json數(shù)據(jù)賦值給all數(shù)組
this.provinces = this.setProvinces(); //篩選all數(shù)組中所有符合省代碼的省信息
},
error => {
console.log(error);
}
);
}
private setProvinces() {
if (this.all !== undefined ) {
const result = new Array<object>();
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'].slice(2, 6) === '0000') { //篩選后4位都為0000的json數(shù)據(jù)
result.push(value);
}
}
return result;
}
}
其中setAll()函數(shù)是將threeLinkService中的setAll()返回的數(shù)據(jù)進(jìn)行處理,然后將數(shù)據(jù)賦值給all數(shù)組,同時(shí)使用setProvince()函數(shù)對(duì)provinces數(shù)組進(jìn)行賦值。
2.第二部分(根據(jù)選擇的省信息,獲取城市信息)
private setCity(province: string) {
if (this.all !== undefined) {
const result = new Array();
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'].slice(0, 2) === province.slice(0, 2)
&& value['item_code'] !== province && value['item_code'].slice(4, 6) === '00') { //選擇前兩位與省代碼一樣的城市代碼,并且后兩位為00的數(shù)據(jù)源
result.push(value);
}
}
return result;
}
}
public selectProvince(code: string) {
this.cityValue = 'undefined'; //重置城市選擇器
this.areaValue = 'undefined'; //重置地區(qū)選擇器
this.citys = this.setCity(code);
}
由于整個(gè)json數(shù)據(jù)部分的結(jié)構(gòu),如下:
{"item_code":"110000","item_name":"北京市"},
{"item_code":"120000","item_name":"天津市"},
{"item_code":"130000","item_name":"河北省"},
{"item_code":"140000","item_name":"山西省"},
所以,我們可以根據(jù)字符串的前兩位來(lái)判斷所選擇的省,然后獲取城市的信息。selectProvince()是一個(gè)響應(yīng)函數(shù),在每次重新選擇省時(shí),都需要重置城市選擇器和地區(qū)選擇器。
3.第三部分(根據(jù)城市信息,獲取地區(qū)信息)
private setArea(city: string) {
if (this.all !== undefined) {
const result = [];
for (let i = 0; i < this.all.length; i++) {
const value = this.all[i];
if (value['item_code'] !== city && value['item_code'].slice(0, 4) === city.slice(0, 4)) {
result.push(value);
}
}
return result;
}
}
public selectCity(code: string) {
this.areaValue = 'undefined'; //每次選擇城市的同時(shí),都重置地區(qū)選擇器
this.areas = this.setArea(code);
}
地區(qū)數(shù)據(jù)的選擇與城市數(shù)據(jù)的選擇一樣,都是根據(jù)城市的唯一代碼進(jìn)行匹配,將所有匹配的地區(qū)數(shù)據(jù)放入areas數(shù)組中
- html代碼部分
<md-select placeholder="請(qǐng)選擇省份" >
<md-option *ngFor="let province of provinces" [value]="province.item_code" (click)="selectProvince(province.item_code);">
{{province.item_name}}
</md-option>
</md-select>
<md-select placeholder="請(qǐng)選擇城市" [(ngModel)]="cityValue">
<md-option *ngFor="let city of citys" [value]="city.item_code" (click)="selectCity(city.item_code);">
{{city.item_name}}
</md-option>
</md-select>
<md-select placeholder="請(qǐng)選擇地區(qū)" [(ngModel)]="areaValue">
<md-option *ngFor="let area of areas" [value]="area.item_code">
{{area.item_name}}
</md-option>
</md-select>
省選擇器的點(diǎn)擊事件就是selectProvince(province.item_code)函數(shù),這函數(shù)可以篩選出后續(xù)的城市信息,重點(diǎn)要強(qiáng)調(diào)的是城市選擇器和地區(qū)選擇器中的[(ngModel)],由于每次重新選擇前面一個(gè)選擇器時(shí),都需要將后面的選擇器進(jìn)行重置,所以這里使用數(shù)據(jù)的雙向綁定的方法,進(jìn)行選擇器的重置,只要將其中的值置為undefined,就可以使選擇器重置。
這個(gè)組件的原理大致就是這樣子,寫(xiě)的有點(diǎn)粗糙,原理可能有些沒(méi)講透,希望讀者可以給我留言或者提問(wèn)
注:這篇博文屬于原創(chuàng)博文,如果有問(wèn)題的可以給我留言,轉(zhuǎn)載注明出處。