Vue2.5开发去哪儿网App 城市列表开发之 兄弟组件间联动及列表性能优化

时间:2023-03-09 03:32:31
Vue2.5开发去哪儿网App 城市列表开发之  兄弟组件间联动及列表性能优化

一,  兄弟组件间联动

1.  点击城市字母,左侧对应显示

给遍历的 字母 添加一个点击事件:

Alphabet.vue

@click="handleLetterClick"
    handleLetterClick (e) {
//获取对应的字母
this.$emit('change', e.target.innerHTML)
}

在 父组件City.vue 中,监听

<city-alphabet :cities="cities" @change="handleLetterChange"></city-alphabet>
    handleLetterChange (letter) {
this.letter = letter
}

然后转发给子CityList组件:

    <city-list :letter="letter"></city-list>

CityList组件,监听:

添加 ref属性      

<div class="area" v-for="(city,key) in cities" :key="key" :ref="key">
<div class="title border-topbottom">{{key}}</div>
<div class="item-list">
<div class="item border-bottom" v-for="c in city" :key="c.id">{{c.name}}</div>
</div>
</div>
 props: ['letter'],
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// better-scrool方法,滚动区自动滚动到元素上
this.scroll.scrollToElement(element)
}
}

Vue2.5开发去哪儿网App 城市列表开发之  兄弟组件间联动及列表性能优化

2.  拖动城市字母表,左侧城市对应滚动

给Alphabet.vue 字母列表绑定事件:

<ul class="list">
<li class="item" v-for="item in letters" :key="item"
@click="handleLetterClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
:ref = 'item'
>{{item}}
</li>
</ul>

事件说明:

touchstart : 触摸开始(手指放在触摸屏上)

touchmove : 拖动(手指在触摸屏上移动)

touchend : 触摸结束(手指从触摸屏上移开)

当前第几个字母   = (触摸处浏览器页面的垂直坐标  -  A 字母距离搜索栏底部的距离) / 每个字母的高度

  methods: {
handleTouchStart () {
//滑动开始
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
// A 字母距离搜索栏底部的距离
const startY = this.$refs['A'][0].offsetTop
      // 79 为:顶部搜索栏 的高度
const touchY = e.touches[0].clientY - 79
const index = Math.floor(touchY - startY) / 20
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}
},
handleTouchEnd () {
     // 滑动结束
this.touchStatus = false
}
}
<template>
<div>
<ul class="list">
<li class="item" v-for="item in letters" :key="item"
@click="handleLetterClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
:ref = 'item'
>{{item}}
</li>
</ul>
</div>
</template> <script>
export default {
name: 'CityAlphabet',
props: ['cities'],
data () {
return {
touchStatus: false
}
},
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerHTML)
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
// A 字母距离搜索栏底部的距离
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('change', this.letters[index])
}
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
}
</script> <style lang="stylus" scoped>
@import "~styles/varibles.styl"
.list
position absolute
right 0
top 1.58rem
bottom 0
display flex
width .4rem
flex-direction column
justify-content center
.item
text-align center
line-height .4rem
color $bgColor
</style>

Alphabet.vue

Vue2.5开发去哪儿网App 城市列表开发之  兄弟组件间联动及列表性能优化

二,列表切换性能优化

1.  滚动的优化

滚动重复执行运算:

this.$refs['A'][0].offsetTop

在 data 中定义 变量

  data () {
return {
startY: 0
}
}
添加生命周期钩子 updated:
  updated () {
this.startY = this.$refs['A'][0].offsetTop
}
     handleTouchMove (e) {
if (this.touchStatus) {
const touchY = e.touches[0].clientY - 79
const index = Math.floor(touchY - this.startY) / 20
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}
}

2. 节流限制 函数   handleTouchMove()  执行的频率

data中  定义   timer: null

  data () {
return {
touchStatus: false,
startY: 0,
timer: null
}

函数的改动:

    handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) {
clearTimeout(this.time)
}
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('change', this.letters[index])
}
}, 16)
}
}

项目地址https://github.com/1417766861/Vue2.5-App/tree/master/Travel