预览图

实现步骤
-
处理后台传来的数据,数据格式化
pySegSort(arr){
if (!String.prototype.localeCompare) return null
// let letters = 'abcdefghjklmnopqrstwxyz'.split('')
let letters = 'ABCDEFGHJKLMNOPQRSTWXYZ'.split('')
let zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('')
let segs = []
letters.forEach((item, i) => {
let cur = { letter: item, data: [] }
arr.forEach((item) => {
if(item.city.localeCompare(zh[i])>=0&&item.city.localeCompare(zh[i+1])<0){
cur.data.push(item)
}
})
if (cur.data.length) {
cur.data.sort(function(a, b) {
return a.city.localeCompare(b, 'zh')
})
segs.push(cur)
}
})
return segs
},
将数据格式化为以下格式
[
{
title:'A'
data:[
{
city:'安康市‘,
id:1
}
]
},
{
title:'B'
data:[
{
city:'北京市‘,
id:2
}
]
},
]
-
利用
Element.scrollTo()
做滑动效果,需要计算出每个字母标题下数组的长度,计算结果放入一个数组中
calculateTotalHeight() {
var list = this.$refs.listGroup
var height = 0
this.listHeight.push(height)
console.log(list.length,'list')
if(list&&list.length>0){
for (var i = 0; i < list.length; i++) {
var item = list[i]
height += item.clientHeight
this.listHeight.push(height)
}
}
}
-
点击侧边字母滑动到对应字母标题
goIndex(params) {
const groupRef = this.$refs.groupRef
const titleRef = this.$refs.titleRef
titleRef.map((item,index) => {
if (item.innerText === params) {
groupRef.scrollTo(0,this.listHeight[index])
}
})
},
html部分
<div class="content">
<div class="top">
<div style="height: 50%;margin:0 0.4rem">
<h5>常用大区</h5>
<div class="one">
<van-tag class="tagsClass" v-for="(area,index) in regionList" :key="index" @click="chooseArea(area)">{{area.regionName}}</van-tag>
</div>
</div>
<div style="height: 50%;margin:0 0.4rem">
<h5>常用城市</h5>
<div class="one">
<van-tag class="tagsClass" v-for="(city,index) in cityList" :key="index" @click="chooseCities(city)">{{city.city}}</van-tag>
</div>
</div>
</div>
<div class="bottom" ref="groupRef">
<ul class="list-shortcut">
<li @click="goIndex(item)" v-for="(item,index) in shortcut" :key="index">{{item}}</li>
</ul>
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<ul >
<li v-for="(item,index) in allList"
class="list-group"
:key="index"
ref="listGroup"
>
<h4 class="list-group-title" ref="titleRef">{{ item.letter }}</h4>
<ul>
<li v-for="city in item.data" @click="chooseCity(city)" class="listitem" :key="city.id">
<span>{{city.city}}</span><span>{{city.regionName}}</span>
</li>
</ul>
</li>
</ul>
</van-list>
</div>
</div>
就完成啦!!
完整代码如下:
<template>
<div class="RegionSelect">
<div class="header">
<!-- 标题栏 -->
<i slot="left" class="iconfont icon-31fanhui1" style="margin: 0.5rem;" @click="$router.go(-1)"/>
<input class="inputClass" id="inut" placeholder="输入城市名进行搜索" @click="searchCity"></input>
<button class="buttonClass" @click="searchCity"><i class="el-icon-search"></i></button>
<div class="areaClass">
<i class="el-icon-location-outline iconClass" ></i>
<span style="font-size: 0.6rem;margin-left:0.2rem;" v-if="city">当前定位城市 {{area}} · {{city}} </span>
<span style="font-size: 0.6rem;margin-left:0.2rem;" v-else>当前定位城市 {{area}} </span>
</div>
</div>
<div class="content">
<div class="top">
<div style="height: 50%;margin:0 0.4rem">
<h5>常用大区</h5>
<div class="one">
<van-tag class="tagsClass" v-for="(area,index) in regionList" :key="index" @click="chooseArea(area)">{{area.regionName}}</van-tag>
</div>
</div>
<div style="height: 50%;margin:0 0.4rem">
<h5>常用城市</h5>
<div class="one">
<van-tag class="tagsClass" v-for="(city,index) in cityList" :key="index" @click="chooseCities(city)">{{city.city}}</van-tag>
</div>
</div>
</div>
<div class="bottom" ref="groupRef">
<ul class="list-shortcut">
<li @click="goIndex(item)" v-for="(item,index) in shortcut" :key="index">{{item}}</li>
</ul>
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<ul >
<li v-for="(item,index) in allList"
class="list-group"
:key="index"
ref="listGroup"
>
<h4 class="list-group-title" ref="titleRef">{{ item.letter }}</h4>
<ul>
<li v-for="city in item.data" @click="chooseCity(city)" class="listitem" :key="city.id">
<span>{{city.city}}</span><span>{{city.regionName}}</span>
</li>
</ul>
</li>
</ul>
</van-list>
</div>
</div>
</div>
</template>
<script>
import defaultImg from "mixins/defaultImg";
import { mapGetters, mapActions } from "vuex";
import {getRegionCityLog,regionCityList,chooseCity } from "service/getData";
// import { Tab, TabItem, Divider } from "vux";
import {Tab,Tag,Tabs, List, Icon} from 'vant';
import { Loadmore } from "mint-ui";
import NewMHeader from 'components/header/MHeader.vue'
import SortBar from "components/item/SortBar.vue";
import SearchHeadRes from "components/search/SearchHeadResult.vue";
import NoResult from "components/search/NoResult.vue";
export default {
name: "RegionSelect",
components: {
NewMHeader,
[Tab.name]: Tab,
[Tabs.name]: Tabs,
[List.name]: List,
[Icon.name]: Icon,
[Tag.name]:Tag
},
data() {
return {
isTouch:false,
touch:{},
allList:[],
initData:[],
loading: false,
finished: false,
cityList:[],
regionList:[],
listHeight: [],
areaList:[],
shortcut:[ 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z'],
area:'内蒙古大区',
city:'呼和浩特',
};
},
computed: {
...mapGetters([
'regionInfo', //默认大区
]),
},
methods: {
...mapActions([
'getRegionInfo', //通过默认地址查询大区
'getRegionInfos', //通过默认地址查询大区
]),
// 处理地区数据
pySegSort(arr){
if (!String.prototype.localeCompare) return null
// let letters = 'abcdefghjklmnopqrstwxyz'.split('')
let letters = 'ABCDEFGHJKLMNOPQRSTWXYZ'.split('')
let zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('')
let segs = []
letters.forEach((item, i) => {
let cur = { letter: item, data: [] }
arr.forEach((item) => {
if(item.city.localeCompare(zh[i])>=0&&item.city.localeCompare(zh[i+1])<0){
cur.data.push(item)
}
})
if (cur.data.length) {
cur.data.sort(function(a, b) {
return a.city.localeCompare(b, 'zh')
})
segs.push(cur)
}
})
return segs
},
// 获取常用城市和大区
async getRegionLog(){
this.area = this.regionInfo[0].regionName
this.city = this.regionInfo[0].city
let list = await regionCityList()
if(list.code == 101){
this.initData = list.data
let lists = await this.pySegSort(list.data)
this.allList = lists
}
let res = await getRegionCityLog({
regionCount:8,
cityCount:10
})
if(res.code == 101){
this.cityList = res.data.cityList
this.regionList = res.data.regionList
}
},
async onLoad() {
},
// 选择城市
async chooseCity(item){
await chooseCity({
id: item.id,
}).then(res => {
if (res.code == 101) {
this.area = item.regionName
this.city = item.city
this.getRegionInfo({province:item.province,city:item.city}) // 修改默认地区\
this.$router.go(-1)
console.log(regionInfo,'regionInfo')
}
}).catch(() => {
});
},
//快捷选择大区
async chooseArea(area){
await chooseCity({
id: area.regionId,
}).then(res => {
if (res.code == 101) {
this.area = area.regionName
this.city = ""
// this.$store.commit('getRegionInfos',{regionName:area.regionName,regionId:area.regionId})
this.getRegionInfos({regionName:area.regionName,regionId:area.regionId}) // 修改默认地区
this.$router.go(-1)
}
}).catch(() => {
});
},
// 快捷选择城市
async chooseCities(city){
var citydata = ''
this.initData.forEach(element => {
if(element.city == city.city){
citydata = element
}
});
await chooseCity({
id: citydata.id,
}).then(res => {
if (res.code == 101) {
this.area = citydata.regionName
this.city = citydata.city
this.getRegionInfo({province:citydata.province,city:citydata.city}) // 修改默认地区
this.$router.go(-1)
}
}).catch(() => {
});
},
// 查找城市
async searchCity(){
this.$router.push('/RegionSearch')
},
goIndex(params) {
const groupRef = this.$refs.groupRef
const titleRef = this.$refs.titleRef
titleRef.map((item,index) => {
if (item.innerText === params) {
groupRef.scrollTo(0,this.listHeight[index])
}
})
},
calculateTotalHeight() {
var list = this.$refs.listGroup
var height = 0
this.listHeight.push(height)
console.log(list.length,'list')
if(list&&list.length>0){
for (var i = 0; i < list.length; i++) {
var item = list[i]
height += item.clientHeight
this.listHeight.push(height)
}
}
}
},
watch: {
// $route(to, from) {
// window.location.reload(); //监测到路由发生跳转时刷新一次页面
// },
},
mounted() {
this.getRegionLog()
setTimeout(()=>{
this.calculateTotalHeight()
}, 2000)
},
destroyed() {
},
};
</script>
<style lang="less" scoped="scoped">
.RegionSelect{
background-color: #fff;
padding: 0.2rem;
height: 100%;
.header{
height: 6%;
.inputClass{
background-color: #f1f8fff9;
position: relative;
z-index: 9999;
height: 1.4rem;
width: 80%;
text-indent: 0.8rem;
border: none;
border-radius: 1.4rem;
margin-top: 0.25rem;
margin-left:0.58rem;
}
.buttonClass{
position: absolute;
color: #ffffff;
font-size: 0.8rem;
top:0.26rem;
right: 0.8rem;
height: 1.3rem;
width: 1.8rem;
border: none;
border-radius: 1.3rem;
background-color:#dcdcdc ;
z-index: 99999;
}
.iconClass{
font-size: 0.7rem;
margin-left: 0.4rem;
}
.areaClass{
display: flex;
align-items: center;
margin-top: 0.6rem;
color:#293F66;
margin-bottom:0.2rem;
font-weight: 500;
}
}
.content{
margin-top: 2rem;
height: 84%;
.top{
height: 35%;
margin-left: 0.6rem;
.one{
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.tagsClass{
background-color: #f1f8fff9 !important;
color: #293F66;
padding:0.2rem 0.5rem;
font-size:0.4rem;
margin-right: 0.5rem;
margin-top: 0.5rem;
}
}
}
.bottom{
height: 65%;
margin: 1rem 0.6rem;
overflow-x: hidden;
overflow-y: auto;
.listitem{
font-size: 0.4rem;
padding: 0.4rem;
margin-right: 0.2rem;
border-bottom: solid 0.02rem rgb(219, 219, 219);
display: flex;
justify-content:space-between;
}
.listitem:hover{
background-color:#f1f8fff9;
}
.list-shortcut{
position: absolute;
z-index: 99999;
right: 0.4rem;
bottom: 10rem;
display: flex;
flex-direction: column;
justify-content: space-around;
height: 10rem;
font-size: 0.4rem;
font-family: $font;
font-weight: 400;
color: #979797;
li {
text-align: center;
cursor: pointer;
}
li:hover{
height: 0.8rem;
width: 0.6rem;
border-radius: 0.8rem;
font-size: 0.6rem;
background-color: #f1f8fff9;
}
}
}
}
}
</style>
版权声明:本文为weixin_43525759原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。