vue实现根据首字母列表点击选择城市
实现点击字母跳转相对应城市,先看下效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7fa61aa407279b998d24e70ebe68e5f4.jpeg)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8c5e0d9439823ca42977695baf7a828b.jpeg)
先获取城市列表
async getCityList() {
//封装的请求调用
const res = await intercept({
method: "general.uppercitylist"//接口参数
});
let arr = [];
if (res.status == true) {
for (let key in res.data.list) {
let obj = {
initial: null,
list: null
};
obj.initial = key;
obj.list = res.data.list[key];
arr.push(obj);
}
this.listData = arr;
console.log(this.listData);
}
},
得到的listData格式是这样的
对数据处理一波,提取字母列表
async getCityList() {
const res = await intercept({
method: "general.uppercitylist"
});
let arr = [];
if (res.status == true) {
for (let key in res.data.list) {
let obj = {
initial: null,
list: null
};
obj.initial = key;
obj.list = res.data.list[key];
arr.push(obj);
}
this.listData = arr;
console.log(this.listData);
// 提取字母列表
this.quickPanelData.forEach((item, index) => {
const navItem = item.navName || item.title || "标题";
this.letterList.push(navItem);
});
// 处理城市列表数据
this.listData.forEach((item, index) => {
this.letterList.push(item.initial);
});
// console.log(this.letterList);
}
},
处理过后的数据
直接奉上全部代码
<template>
<div class="selectCityMain" ref="DOM">
<div ref="Box">
<div v-if="letter.length > 0" class="now-sort">{{letter}}</div>
<div :class="['now-letter', fadeFlag?'fadeIn':'']">{{letter}}</div>
<div class="letterBox">
<p :class="idx === activtIndex?'active':''" v-for="(item,idx) in letterList" :key="idx" @click="scrollSelect(idx)">{{item}}</p>
</div>
<div>
<div class="hostCityBox">
<div
class="base-wrap"
v-for="(item, index) in quickPanelData"
:classesAttr="item"
:key="index"
>
<div class="title">{{item.title}}</div>
<div class="panel host" ref="host">
<span
class="item"
v-for="(cy,idx) in item.data"
:key="idx"
@click="selectCity(cy)"
>{{cy}}</span>
</div>
</div>
</div>
<div class="cityListBox">
<div class="base-wrap" v-for="(tle,tleIdx) in listData" :key="tleIdx">
<div class="title">{{tle.initial}}</div>
<div class="panel">
<p
class="cityName"
v-for="(city,idx1) in tle.list"
:key="idx1"
@click="selectCity(city.name)"
>{{city.name}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { intercept } from "../../service/api";
import config from "../../utils/config";
export default {
data() {
return {
cityname: "",
citycode: "",
city: "",
province: "",
listData: [],
letterList: [],
letter: "",
fadeFlag: false,
scrolly: 0,
activtIndex:0,
quickPanelData: [
{
title: "当前城市",
navName: "当前",
data: [this.$store.getters.cityname],
},
{
title: "热门城市",
navName: "热",
data: [
"北京市",
"上海市",
"广州市",
"深圳市",
"成都市",
"重庆市",
"杭州市",
"三亚市",
"武汉市"
],
}
]
};
},
async created() {
this.getCityList();
},
mounted() {
// 先给页面注册滚动事件
window.addEventListener("scroll", this.handleScroll, true);
},
methods: {
handleScroll() {
var scrollTop = document.documentElement.scrollTop;
},
// 获取城市列表
async getCityList() {
const res = await intercept({
method: "general.uppercitylist"
});
let arr = [];
if (res.status == true) {
for (let key in res.data.list) {
let obj = {
initial: null,
list: null
};
obj.initial = key;
obj.list = res.data.list[key];
arr.push(obj);
}
this.listData = arr;
console.log(this.listData);
// 提取字母列表
this.quickPanelData.forEach((item, index) => {
const navItem = item.navName || item.title || "标题";
this.letterList.push(navItem);
});
// 处理城市列表数据
this.listData.forEach((item, index) => {
this.letterList.push(item.initial);
});
}
},
//计算滚动条滚动的距离
scrollSelect(index) {
this.letter = this.letterList[index];
this.fadeFlag = true;
this.activtIndex = index;
this.Timer = setTimeout(() => {
this.fadeFlag = false;
}, 1000);
let scrolly = 0;
//热门城市自适应高度获取元素的高度
let hostHeight = document.getElementsByClassName("host")[1].offsetHeight;
let topHeght = 132 + hostHeight;
if (index === 0) {
this.scrolly = 0;
} else if (index === 1) {
this.scrolly = 92;
} else if (index === 2) {
this.scrolly = topHeght;
} else if (index >= 3) {
let len = 0;
this.listData.forEach((item, idx) => {
if (idx < index - 2) {
len += item.list.length;
}
});
this.scrolly = topHeght + (index - 2) * 40.8 + len * 35;
}
document.documentElement.scrollTop = this.scrolly;
},
//点击选择城市
selectCity(name) {
this.cityname= name;
this.$store.commit("changeCityName", name);
this.$router.push({ path: "/home" });
},
async onSelected(data) {
//选择城市动态更新到首页
this.cityname = data.city.value;
this.$store.commit("changeCityName", this.cityname);
this.$router.push({ path: "/home" });
}
},
computed: {
isFollow() {
return this.$store.getters.cityname; //监听城市名字改变
}
},
watch: {
async isFollow(newVal, oldVal) {
const res = await intercept({
method: "general.getcityid",
name: this.$store.getters.cityname
});
this.citycode = res.data.list.id;
this.$store.commit("changeCityCode", this.citycode);
}
}
};
</script>
<style lang="scss" scoped>
.selectCityMain {
width: 100%;
// height: 500px;
// height: 100%;
overflow-y: auto;
position: relative;
.letterBox {
width: 35px;
position: fixed;
top: 18%;
right: 0;
background: rgba(0, 0, 0, 0.5);
border-radius: 16px;
padding: 10px 0;
p {
font-size: 12px;
color: #fff;
text-align: center;
padding-bottom: 3px;
}
.active{
background: rgba(0, 0, 0, 0.5);
}
}
.now-letter {
font-size: 60px;
color: #ccc;
position: fixed;
top: 60%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
opacity: 0;
&.fadeIn {
animation: fade 1s linear 0ms;
opacity: 1;
}
}
.now-sort {
position: absolute;
top: 0;
left: 0;
width: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
font-size: 14px;
padding: 10px;
background: #ccc;
}
.hostCityBox {
width: 100%;
.base-wrap {
overflow: hidden;
.title {
display: flex;
align-items: center;
box-sizing: border-box;
font-size: 14px;
padding: 10px;
background: #ccc;
}
.panel {
display: flex;
flex-wrap: wrap;
font-size: 14px;
padding: 10px;
padding-right: 30px;
.item {
display: flex;
align-items: center;
justify-content: center;
width: 74px;
border: 1px solid;
border-radius: 10px;
margin-bottom: 10px;
margin-right: 8px;
}
&::after {
display: block;
content: "";
width: 200px;
border: 1px solid transparent;
}
}
}
}
.cityListBox {
width: 100%;
.title {
display: flex;
align-items: center;
box-sizing: border-box;
font-size: 14px;
padding: 10px;
background: #ccc;
}
.panel {
display: flex;
flex-wrap: wrap;
font-size: 14px;
padding: 0 10px;
padding-right: 30px;
.cityName {
font-size: 14px;
width: 100%;
height: 35px;
display: flex;
align-items: center;
}
}
}
}
</style>