点击城市列表页的字母显示对应的城市区块
1.Alphabet组件中(子)
确认点击的是哪个字母,传递给父组件City,是子传父
使用$emit
<template>
<div class="list">
<div class="item" v-for="item in letters" :key="item" :ref="item"
@click="handleLetterClick"
@touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchEnd="handleTouchEnd">
{{item}}
</div>
</div>
</template>
为每个字母注册click点击事件,点击相应字母时触发LetterChange
事件,并将事件传递给父组件
methods中
handleLetterClick (e) {
this.$emit('LetterChange', e.target.innerText)
},
2.City组件中(父)
父组件监听字母的变化,并将点击的字母传递给List组件,是父传子
使用props
<template>
<div>
<city-header></city-header>
<city-list :cities="cities" :hotCities="hotCities" :city="city" :letter="letter"></city-list>
<city-alphabet :cities="cities" @LetterChange="handleLetterChange"></city-alphabet>
</div>
</template>
在父组件对应模板中为LetterChange
事件设置该事件的处理函数handleLetterChange
,拿到点击的字母letter
;
并通过动态属性绑定的方式,将该属性绑定到子组件List中:letter="letter
methods中
handleLetterChange (letter) {
this.letter = letter
}
3.List组件中(子)
根据父组件传递过来的字母,显示对应的城市列表,是子传父
使用$emit
props: {
cities: Object,
hotCities: Array,
city: String,
letter: String
},
List组件在props
中接收父组件传递过来的属性letter
,知道点击的是哪一个字母,通过watch
方法监听letter
变化,显示对应的城市列表即可
watch: {
letter () {
if (this.letter) {
const ele = this.$refs[this.letter][0]
this.scroll.scrollToElement(ele)
}
}
}
滑动字母条城市区块随之变化
1.Alphabet组件中(子)
为每个字母添加原生的滑动事件,通过计算滑动的位置与A
字母位置的差值,再除以每个字母的高度可得到当前是在哪一个字母
@touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchEnd="handleTouchEnd"
//将cities对象变为一个数组['A','B'...]
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
methods: {
handleLetterClick (e) {
this.$emit('LetterChange', e.target.innerText)
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
const startY = this.$refs['A'][0].offsetTop
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('LetterChange', this.letters[index])
}
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
2.City组件中(父)
在父组件对应模板中为LetterChange
事件设置该事件的处理函数handleLetterChange
,拿到当前滑动所在的字母letter
;
并通过动态属性绑定的方式,将该属性绑定到子组件List中:letter="letter
在这里插入代码片
3.List组件中(子)
通过watch
方法监听letter
变化,显示对应的城市列表即可
watch: {
letter () {
if (this.letter) {
const ele = this.$refs[this.letter][0]
this.scroll.scrollToElement(ele)
}
}
}
4.滑动时的性能优化
防抖:滑动字母时一直在触发LetterChange
事件
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - this.startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('LetterChange', this.letters[index])
}
}, 16)
}
},