左右联动的时候右边高亮显示的对不上

来源:5-9 listview 基础组件的开发和应用-滚动固定标题实现(上)

小徐子是我

2019-02-26

在这里输入代码<template>
  <scroll 
    class="listview" 
    ref="listview"
    @scroll="scroll"
    :listen-scroll="listenScroll"
    :probe-type = "probeType"
  >
    <ul>
      <li v-for="(group, index) in data" :key="index" ref="listgroup" class="list-group">
        <!-- 热门 -->
        <h2 class="list-group-title">{{group.title}}</h2>
        <ul>
          <li v-for="(item, index) in group.items" class="list-group-item" :key="index">
            <img class="avatar" v-lazy="item.avatar" alt>
            <span class="name">{{item.name}}</span>
          </li>
        </ul>
      </li>
    </ul>
    <div class="list-shortcut" >
      <ul>
        <!-- 右侧字母 -->
        <li v-for="(item, index) in shortcutList"   @touchstart.stop.prevent="onShortcutTouchStart" @touchmove.stop.prevent="onShortcutTouchMove"
        :data-index="index" 
        :key="index" 
        class="item"
        :class="{'current' : currentIndex === index}">{{item}}</li>
      </ul>
    </div>
    <!-- <div class="list-fixed">
      <div class="fixed-title">{{fixedTitle}}</div>
    </div> -->
    <div class="loading-container" v-show="!data.length">
      <loading></loading>
    </div>
  </scroll>
</template>

<script type="text/ecmascript-6">
import Loading from "base/loading/loading";
import Scroll from "base/scroll/scroll";
import {getData} from "common/js/dom"

const ANCHOR_HEIGHT = 18

export default {
  props: {
    // 已经在父组件处理好的数据
    data: {
      type: Array,
      default: [],
    }
  },
  computed: {
    // 右侧字母
    shortcutList() {
      // data的每个元素
      return this.data.map(group => {
        // 选择一个字母  热
        return group.title.substr(0, 1);
      });
    },
    fixedTitle() {
      // console.log(this.scrolly)
      if (this.scrolly > 0) {
        return "";
      }
      // return this.data[this.currentIndex] ?
    }
  },
  created() {
    
    this.probeType = 3,
    this.touch = {},
    this.listenScroll = true,
    this.listHeight = []
  },
  data() {
    return {
      scrollY: -1,
      currentIndex: 0,
      diff: -1
    };
  },
  methods: {
    onShortcutTouchStart(e) {
      // 获取当前点击的index
      let anchorIndex = getData(e.target, 'index')
      // 第一次触碰的位置
      let firstTouch = e.touches[0]
      this.touch.y1 = firstTouch.pageY
      this.touch.anchorIndex = anchorIndex
      this._scrollTo(anchorIndex)
    },
    onShortcutTouchMove(e) {
      // 离开的位置
      // 减去第一次触碰的位置然后除以元素高18px就可以拿到有几个元素
      let firstTouch = e.touches[0]
      this.touch.y2 = firstTouch.pageY
      // 滑动了几个元素
      let delta = (this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT | 0
      // 第一次触碰的位置加上滑动了几个元素
      let anchorIndex = parseInt(this.touch.anchorIndex) + delta
      this._scrollTo(anchorIndex)
    },
    scroll(pos) {
      this.scrollY = pos.y
    },
    _scrollTo(index) {
      console.log(index)
      if (!index && index !== 0) {
        return
      }
      // 如果超出顶部
      if(index < 0) {
        alert('超出顶部')
        index = 0
        // 或者超出底部
      } else if (index > this.listHeight.length -2) {
        index = this.listHeight.length -2
      }
      this.$refs.listview.scrollToElement(this.$refs.listgroup[index], 0)
      // 获取y轴向上的距离
      // this.scrollY = this.$refs.listview.scroll.y
      this.scrollY = this.listHeight[index]
    },
    _calculateHeight() {
      this.listHeight = []
      const list = this.$refs.listgroup
      let height = 0
      
      for (let i = 0; i < list.length; i++) {
        let item = list[i]
        height += item.clientHeight
        this.listHeight.push(height)
      }
    }
  },
  watch: {
    data() {
      setTimeout(() => {
        this._calculateHeight()
      },20)
    },
    scrollY(newY) {
      // 向上滑动 newy 是负值
      // console.log(newY)
      // console.log(this.data)
      // 获取所有的高度
      const listHeight = this.listHeight
      // 如果大于0 就说明超出顶部
      if(newY > 0) {
        this.currentIndex = 0
        return
      }

      for (let i = 0; i < listHeight.length - 1; i++) {
        let height1 = listHeight[i]
        let height2 = listHeight[i + 1]
        console.log('height1', height1)
        console.log('height2', height2)
        console.log('i', i)
        if(-newY >= height1 && -newY < height2) {
          this.currentIndex = i
          // console.log(this.currentIndex)
          return
        }
      }
      this.currentIndex = listHeight.length -2
    }

  },
  components: {
    Scroll,
    Loading
  }
};
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
@import '~common/stylus/variable'
.listview
  position relative
  width 100%
  height 100%
  overflow hidden
  background $color-background
  .list-group
    padding-bottom 30px
    .list-group-title
      height 30px
      line-height 30px
      padding-left 20px
      font-size $font-size-small
      color $color-text-l
      background $color-highlight-background
    .list-group-item
      display flex
      align-items center
      padding 20px 0 0 30px
      .avatar
        width 50px
        height 50px
        border-radius 50%
      .name
        margin-left 20px
        color $color-text-l
        font-size $font-size-medium
  .list-shortcut
    position absolute
    z-index 30
    right 0
    top 50%
    transform translateY(-50%)
    width 20px
    padding 20px 0
    border-radius 10px
    text-align center
    background $color-background-d
    font-family Helvetica
    .item
      padding 3px
      line-height 1
      color $color-text-l
      font-size $font-size-small
      &.current
        color $color-theme
  .list-fixed
    position absolute
    top 0
    left 0
    width 100%
    .fixed-title
      height 30px
      line-height 30px
      padding-left 20px
      font-size $font-size-small
      color $color-text-l
      background $color-highlight-background
  .loading-container
    position absolute
    width 100%
    top 50%
    transform translateY(-50%)
</style>

写回答

1回答

ustbhuangyi

2019-02-27

  1. 建议仔细对比我的 GitHub 源码

  2. 可以考虑直接用 cube-ui 的 IndexList 组件:https://didi.github.io/cube-ui/#/zh-CN/docs/index-list

  3. 可以参考 IndexList 组件的实现:https://github.com/didi/cube-ui/blob/dev/src/components/index-list/index-list.vue

0
23
小徐子是我
回复
ustbhuangyi
谢谢老师.....丢人了......
2019-03-05
共23条回复

Vue2.0高级应用教学实战,开发企业级移动端音乐Web App

Vue.js高级知识应用大集合,实战企业级APP,教你搞定组件化开发。

5432 学习 · 3804 问题

查看课程