vue实现城市索引列表
Vue 实现城市索引列表
数据结构准备
城市数据通常以数组形式存储,每个城市对象包含名称和拼音首字母。示例数据结构如下:
const cities = [
{ name: '北京', pinyin: 'bj' },
{ name: '上海', pinyin: 'sh' },
{ name: '广州', pinyin: 'gz' },
// 更多城市...
]
按字母分组
使用 reduce 方法将城市按首字母分组:
const groupedCities = cities.reduce((acc, city) => {
const initial = city.pinyin[0].toUpperCase()
if (!acc[initial]) acc[initial] = []
acc[initial].push(city)
return acc
}, {})
模板结构
在 Vue 模板中创建左右布局,左侧为城市列表,右侧为字母索引栏:
<div class="city-container">
<div class="city-list">
<div v-for="(group, initial) in groupedCities" :key="initial">
<h3>{{ initial }}</h3>
<div v-for="city in group" :key="city.name" @click="selectCity(city)">
{{ city.name }}
</div>
</div>
</div>
<div class="index-bar" @touchstart="onTouchStart" @touchmove="onTouchMove">
<div v-for="initial in initials" :key="initial" @click="scrollTo(initial)">
{{ initial }}
</div>
</div>
</div>
索引栏交互
实现索引栏的触摸事件处理:
methods: {
scrollTo(initial) {
const element = document.querySelector(`h3:contains('${initial}')`)
if (element) element.scrollIntoView()
},
onTouchStart(e) {
this.handleTouch(e)
},
onTouchMove(e) {
this.handleTouch(e)
},
handleTouch(e) {
const indexHeight = e.currentTarget.offsetHeight
const itemHeight = indexHeight / this.initials.length
const touchY = e.touches[0].clientY - e.currentTarget.getBoundingClientRect().top
const index = Math.floor(touchY / itemHeight)
if (index >= 0 && index < this.initials.length) {
this.scrollTo(this.initials[index])
}
}
}
样式优化
添加必要的基础样式确保布局合理:
.city-container {
display: flex;
height: 100vh;
}
.city-list {
flex: 1;
overflow-y: auto;
}
.index-bar {
width: 20px;
display: flex;
flex-direction: column;
align-items: center;
background: #f5f5f5;
}
性能优化
对于大数据量情况,建议:
- 使用虚拟滚动技术
- 添加防抖处理滚动事件
- 考虑使用 Web Worker 处理数据分组
完整组件示例
export default {
data() {
return {
cities: [...], // 城市数据
groupedCities: {},
initials: []
}
},
created() {
this.groupCities()
},
methods: {
groupCities() {
this.groupedCities = this.cities.reduce((acc, city) => {
const initial = city.pinyin[0].toUpperCase()
if (!acc[initial]) acc[initial] = []
acc[initial].push(city)
return acc
}, {})
this.initials = Object.keys(this.groupedCities).sort()
},
// 其他方法...
}
}
这种实现方式提供了完整的城市索引功能,包括字母分组、快速导航和触摸交互,适合大多数移动端和PC端应用场景。






