07-City组件开发-点击/滑动字母显示对应城市区域

点击城市列表页的字母显示对应的城市区块

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)
     }
 },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值