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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值