• 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

  • 相关阅读:
    vue生命周期过程做了什么
    css_css3_实用属性_随时补充更新
    echarts的symbol引用本地图片写法
    无废话设计模式(1)--简单工厂、工厂方法、抽象工厂
    JavaWeb--Maven学习
    SpringCloud Alibaba实战 -引入服务网关Gateway
    从ReentrantLock看AQS (AbstractQueuedSynchronizer) 运行流程 抽象的队列式同步器
    架构的搭建(一)SpringCloud Alibaba
    配置中心之Nacos简介,使用及Go简单集成
    RabbitMQ
  • 原文地址:https://www.cnblogs.com/donghaoblogs/p/10438290.html
Copyright © 2020-2023  润新知