vue实现城市索引列表
实现城市索引列表的步骤
数据准备
城市数据通常以数组形式存储,每个城市对象包含名称和拼音首字母。例如:
const cities = [
{ name: '北京', pinyin: 'bj' },
{ name: '上海', pinyin: 'sh' },
{ name: '广州', pinyin: 'gz' },
// ...
]
组件结构
创建Vue组件时,需要包含以下部分:

- 城市列表展示区域
- 右侧字母索引栏
- 顶部当前选中字母提示
<template>
<div class="city-list">
<div v-if="currentLetter" class="current-letter">{{ currentLetter }}</div>
<div class="list-wrapper">
<div v-for="(group, letter) in groupedCities" :key="letter">
<div class="letter-title">{{ letter }}</div>
<div
v-for="city in group"
:key="city.name"
class="city-item"
@click="selectCity(city)"
>
{{ city.name }}
</div>
</div>
</div>
<div class="index-bar">
<div
v-for="letter in letters"
:key="letter"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
{{ letter }}
</div>
</div>
</div>
</template>
数据处理
使用computed属性对城市数据进行分组:
computed: {
groupedCities() {
return this.cities.reduce((acc, city) => {
const letter = city.pinyin[0].toUpperCase()
if (!acc[letter]) acc[letter] = []
acc[letter].push(city)
return acc
}, {})
},
letters() {
return Object.keys(this.groupedCities).sort()
}
}
触摸交互
实现右侧字母索引的触摸交互功能:

methods: {
handleTouchStart(e) {
this.touchStartY = e.touches[0].clientY
this.scrollToLetter(this.getLetterFromTouch(e))
},
handleTouchMove(e) {
this.scrollToLetter(this.getLetterFromTouch(e))
},
getLetterFromTouch(e) {
const index = Math.floor((e.touches[0].clientY - this.touchStartY) / 20)
return this.letters[Math.max(0, Math.min(index, this.letters.length - 1))]
},
scrollToLetter(letter) {
this.currentLetter = letter
const element = document.querySelector(`[data-letter="${letter}"]`)
if (element) element.scrollIntoView()
}
}
样式设计
关键CSS样式示例:
.city-list {
position: relative;
height: 100vh;
}
.list-wrapper {
height: calc(100% - 50px);
overflow-y: auto;
}
.index-bar {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
align-items: center;
}
.current-letter {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
background-color: rgba(0,0,0,0.5);
color: white;
}
性能优化
对于大量城市数据,可以考虑:
- 使用虚拟滚动技术
- 添加防抖处理触摸事件
- 对字母索引进行节流处理
完整实现需要考虑浏览器兼容性和移动端触摸体验,可以通过添加更多交互反馈(如震动效果)来提升用户体验。





