• [Vue音乐项目] 第九节 歌手页面(点击跳转+滑动联动)


    上一节完成了页面的展示及滚动效果,接下来实现歌手列表和歌手索引的联动效果,点击右侧的字母,中间跳转到相应的歌手位置,滑动歌手页面时,右侧的字母列表也随之改变。

    1. 打开src/base/listview/index.vue(没有则创建),实现点击跳转

      //实现原理: 因为字母列表索引和歌手列表相对应,在触屏开始的时候,记录下开
      //始索引index及当前元素位于浏览器器的
      //Top偏移值y1;在触屏移动的时候,记录下当前top偏移值y2,根据(y2-y1)/元素高度
      //得到偏移索引,开始索引index+偏移索引等于当前索引。把当前
      //索引传递进_scrollTo,
      
      <template>
          <ul>
              <li ref="grouplist">
                  <h2> ... </h2>
                  <ul>
                      <li ref="itemlist">
                  </ul>
              </li>
          </ul>
          //添加两个事件监听,1.触屏开始 2.触屏移动
          <div class="list-shortcut" @touchStart="onTS" @touchMove.top.prevent="onTM">
              
          </div>
      </template>
      <script>
          export default {
              created() {
                  this.touch = {},
              }
              methods: {
                  //[1] 为索引列表添加触屏开始事件处理程序
                  onTS(e) {
                      //获取开始li元素的data_index属性
                      let index = getData(e.target,'index')
                      //获取开始li元素的偏移值
                      this.touch.y1 = e.touchs[0].pageY
                      //放置当前索引
                      this.touch.index = index
                      //[3] 歌手列表滚动到指定位置
                      this._scrollTo(index)
                  },
                  //[2] 为索引列表添加触屏移动事件处理程序
                  onTM(e) {
                      //保存当前li元素的偏移值
                      this.touch.y2 = e.touchs[0].pageY
                      //获取偏移索引
                      let offset = (this.touch.y2-this.touch.y1) / 18 | 0
                      //计算得出当前索引
                      let index = parseInt(this.touch.index) + offset
                      //[3] 歌手列表滚动到指定位置
                      this._scrollTo(index)
                  },
                  //[方法] 歌手列表滚动到指定位置
                  _scrollTo(index) {
                      //对index做预先处理 ps: heights最后两个高度是多余的
                      if(!index && index!=0) return 
                      if(index < 0) {
                          index = 0
                      } else if(index > this.heights.length - 2) {
                          index = this.heights.length - 2
                      }
                      //滚动歌手列表  ps:方法scrollToElement在Scroll组件定义
                      this.$refs.listview.scrollToElement(this.$refs.grouplist[index],0)
                  }
              },
          }
      </script>
      
      //scr/base/scroll/index.vue,methods添加以下方法
      scrollToElement() {
          this.scroll && this.scroll.scrollToElement.apply(this.scroll,arguments)
      }
      //scr/common/js/dom.js 添加以下内容
      export function getData(el,name,value) {
          const prefix = 'data-'
          name = prefix + name
          if(value) {
              return el.setAttribute(name,value)
          } else {
              return el.getAttribute(name)
          }
      }
      
    2. 实现两边联动效果

      <template>
          //[2.1] 滚动时,添加监听函数
          <m-scroll @scroll="scroll" >
              <ul>
                  <li>
                      <h2> ... </h2>
                      <ul>
                          //[3] 动态改变右侧字母索引的样式
                          <li :class="{'current': currentIndex == index}" >
                      </ul>
                  </li>
              </ul>
              <div>
                  
              </div>
              //[fixed 1](共三步) 歌手列表固定栏 通过fixed变量动态改变
              <div class="list-fixed" v-show="fixedTitle" ref="fixed">
                  <div class="fixed-title">{{fixedTitle}}</div>
              </div>
          </scroll>
      </template>
      <script>
          export default {
              computed: {
                  //[fixed 2] 计算是否固定
                  fixed() {
                      if(this.scrollY > 0) return undefined
                      return this.data[this.currentIndex] ? 
                      this.data[this.currentIndex].title : undefined
                  }
              },
              methods: {
                  //如果手动点击,更新歌手列表的ScrollY值
                  scroll() {
                     ...
                     this.scrollY = -this.heightList[index]
                  },
                  _calculateHeight() {
                      var height = 0
                      this.heightList.push(height)
                      for(let i=0; i<this.$refs.listgroup.length; i++) {
                          height += this.$refs.listgroup[i].clientHeight
                          this.heightList.push(height)
                      }
                  },
                  //[2.2] 监听处理函数,赋值给scrollY
                  scroll(pos) {
                      this.scrollY = pos.y
                  }
              },
              watch: {
                  data() {
                      //[1]  获取歌手列表各分组高度
                      this._calculateHeight()
                  },
                  //[3] scrollY变化时,处理得到currentIndex
                  scrollY(newValue) {
                      if(newY > 0) {
                          this.currentIndex = 0
                          return
                      }
                      for(let i=0; i<this.heightList.length; i++) {
                          let height1 = this.heightList[i]
                          let height2 = this.heightList[i+1]
                          if(-newY >= height1 && -newY < height2) {
                              this.currentIndex = i
                              [fixed 3] 监听父组到顶部的距离,固定栏减少该段距离
                              this.diff = height2 + newY
                              return
                          }
                      }
                      this.currentIndex = this.heightList.length - 2
                  }
              },
              //实现固定栏逐渐减少高度的动画,平滑过渡
              diff(newVal) {
                  let fixedTop = (newVal>0 && newVal<30) ? newVal - 30 : 0
                  if(this.fixedTop == fixedTop) return
                  this.fiexedTop = fixedTop
                  this.$refs.fixed.style.transform = `translate3d(0,${fixedTop}px,0)`
              }
          }
      </script>
      
  • 相关阅读:
    关于android中两种service的编写简单总结
    To learn list
    android中如何在系统启动的时候启动自己的service
    service的生命周期以及两种service的差异
    Intent的简单概述
    关于startactivity初始化activity的过程以及activity和window以及view的关系
    android activity生命周期的一张经典图片
    关于Android进程的启动和消亡
    Java基础学习总结(73)——Java最新面试题汇总
    Beetl学习总结(4)——Web集成
  • 原文地址:https://www.cnblogs.com/juetan/p/13861304.html
Copyright © 2020-2023  润新知