實現效果如下:
一、右側有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;
}