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) } }

 

 技术图片

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

技术图片

二,列表切换性能优化

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

 

相关文章