angular2--怎麼實現城市列表選擇功能,類似於通信錄功能

實現效果如下:

一、右側有26個字母,用戶點擊字母的時候,列表會跳到對應字母的城市區域
二、頁面滑動的時候,經過的城市區域,在右側字母列表處有高亮提示
三、用戶選擇一個城市的時候,選擇的城市信息會顯示在頭部==》當前城市位置

代碼實現步驟:

一、在頭部定義一個盒子,用於接收用戶選擇的城市

<div class="city-box">
  <div class="city-header">當前城市</div>
  <div class="city-body city-list" *ngIf="cityType">
      <div class="city-item active">{{cityType}}</div>
   </div>
</div>

二、接着就是要循環渲染各個字母對應的城市名稱列表了

<div class="city-box" #cityBox (scroll)="noscroll($event)">
    <div *ngFor="let item of cityList">
       <!-- 對應的英文字母-->
      <p class="city-header" [id]="'city-'+item.cityIndex">{{item.cityIndex}}</p>     
       <!-- 每個對應字母下的城市列表-->
      <div class="city-body city-list border-btm">    
        <div class="city-item" *ngFor="let i of item.cityList" (click)="chooseCity(i.id,i.name)"
             [ngClass]="{'active':cityType==i.name}">{{i.name}}</div>
      </div>
    </div>
</div>

根據前端的代碼渲染格式,我們希望就是拿到的城市數組是這樣的:
在這裏插入圖片描述
但有時候,後臺拿到的數據格式不是我們想要的,如下面:
在這裏插入圖片描述
所以我們要格式化一下數組:

// 格式化數據
_normalizeCity(listObj) {
	let listArray = [];
	if(typeof listObj === 'object') {
		for(let key in listObj) {
			if(listObj[key]) {
				listArray.push({
					cityIndex: key,
					cityList: listObj[key]
				});
			}
		}
	}

	return listArray;
}
this.cityList = this._normalizeCity(result.data);   //result.data爲上面拿到的數組

三、右邊的字母列表
用到的數組還是上面那個數組

<div class="list-shortcut" *ngIf="!inputing">
	<ul>
		<li *ngFor="let item of cityList" [ngClass]="{active:index==item.cityIndex}" class="item" (click)="positionIndex(item.cityIndex)">{{item.cityIndex}}</li>
	</ul>
</div>

四、主要的ts代碼

index: string = 'A'; //當前選中的字母
offsetTops: Array<any> = [];   //每個字母距離頂部的距離
cityType: any;
cityId: any;
hotCityLists: any = []; //熱門城市
// 所有城市列表
cityList: Array < any > = [];
keyword: string = '';


ngAfterViewInit(){
	setTimeout(() => {
		this.cityList.forEach((item, index) => {
			let offsetTop = document.getElementById('city-' + item.cityIndex).offsetTop;
			this.offsetTops.push(offsetTop)
		});
	}, 500);
}
	
scrollFn(event) {
	const threshold = 60; //字母標題的高度
	if(event.target.scrollTop < threshold) {
		this.index = this.cityList[0].cityIndex;
		return;
	}
	this.offsetTops.forEach((item, index) => {
		if(event.target.scrollTop + threshold >= this.offsetTops[index]) {
			this.index = this.cityList[index].cityIndex;
			return;
		}
	});
}

// 獲取熱門城市
	getHotCities() {
		let params = {};
		this.httpService.getHotCities(params).then(result => {
			if(result.code == 'FAILED') {
				Commons.showToast(result.msg);
			} else {
				this.hotCityLists = result.data;
			}
		}, error => {

		});
	}

	//獲取城市列表
	getCitys() {
		let params = {};
		this.httpService.getCitys(params).then(result => {
			if(result.code == 'FAILED') {
				Commons.showToast(result.msg);
			} else {
				this.cityList = this._normalizeCity(result.data);
				console.log(this.cityList)
			}
		}, error => {

		});
	}
	
	// 格式化數據
	_normalizeCity(listObj) {
		let listArray = [];
		if(typeof listObj === 'object') {
			for(let key in listObj) {
				if(listObj[key]) {
					listArray.push({
						cityIndex: key,
						cityList: listObj[key]
					});
				}
			}
		}
	
		return listArray;
	}

	//選擇城市
	chooseCity(id, name) {
		this.cityType = name;
		this.cityId = id;
		// 改變搜索輸入狀態
		this.inputing = false;
		this.keyword = '';
	}
	
	//滑動右邊字母選擇
	positionIndex(index) {
		this.getCitys();
	
		this.index = index;
		let offsetTop = document.getElementById('city-' + this.index).offsetTop;
		this.content.nativeElement.scrollTop = offsetTop;
	
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章