vue-music(8) list组件和list组件中的快速入口bar的联动

这里写图片描述

list组件整体式一个大Scroll组件,点击每个歌手,进入歌手页面,此处用到的是二级路由

二级路由

<li @click="selectItem(item)" v-for="item in group.items" :key="item.id" class="list-group-item">

添加点击事件

selectItem (item) {
      this.$emit('select', item) // 向外派发点击事件 创出被点击的内容 父组件监听,把点击的歌手item当实参传出
},

父组件

<list :data="list" @select="selectSinger" ref="list"></list>
    ...

二级路由的跳转

selectSinger (item) {
      this.$router.push({ // 跳转路由
        path: `/singer/${item.id}` // 此处id前面不需要加 ‘ :’
      })
      this.setSinger(item) // 2.实现数据提交到state
},

在 router/index.js 配置二级路由

router: [
    { 
        path: '/singer',
        component: 'Singer',
        children: [
            { 
                path: ':id', // 注意冒号不要掉
                component: 'SingerDetail'
            }
        ]
    }
]

左边列表和右边快速入口bar的联动
在bar的div上添加 事件@touchMove, @touchstart, 实现滑动效果。为了取消冒泡,添.stop.prevent

<div class="list-shortcut" @touchstart.stop.prevent="onShortCutTouchStart" @touchmove.stop.prevent="onShortCutTouchMove">
    <ul>
          <li v-for="(item,index) in shortCutList" :key="item.id" class="item" :class="{'current':currentIndex===index}" :data-index="index">{{item}}</li>
        </ul>
</div>  
created () {
    this.touch = {} // 定义一个对象用来接收移动的属性
    this.listernScroll = true
    this.listHeight = []
    this.probeType = 3 // bs 类型
  },
data () {
    return {
      // click: true,
      scrollY: -1,
      currentIndex: 0,
      diff: -1
    }
},
  。。。
onShortCutTouchStart(e){
    let touchIndex = getData(e.target, 'index') // 调用getData函数,添加index属性
    this.touch.y1 = e.touches[0].pageY // 第一次触摸的y坐标
    this.touch.chapter = touchIndex // 触摸到第几个字母
    this._scrollTo(touchIndex) //执行跳转函数
}
onShortCutTouchMove(e){\
    this.touch.y2 = e.touches[0].pageY // 触摸中的y坐标、
    let dleta = (this.touch.y2 - this.touch.y1) / CHAPTER_HEIGHT | 0 // CHAPTER_HEIGHT是字母的高度,根据样式来的。 |0 向下取整 => 得到移动的字母数
    let touchIndex = parseInt(this.touch.chapter) + delta // 从记录的起始字母开始移动
    this._scrollTo(touchIndex)
},
scroll (position) {
      this.scrollY = position.y // bs自带函数  获得实时滚动的y坐标
},
_scrollTo(index){
    if (!index) { // 没有点击到bar的字母,不会执行跳转
        return
    }
    // 如果 touchmove 超出范围
    if (index < 0) {
        index = 0
    } else if (index > this.listHeight[index - 2]) {
        index = this.listHeight[index - 2]
    }
    // 使整个的scroll跳转到特定的index位点上,而index是根据右边bar滑动或点击而来的,这样完成左右联动
    this.$refs.listView.scrollToElement(this.$refs.listGroup[index], 0) // 0 是缓动时间   scrollToElement是Bscroll 组件中封装的函数,能跳转到指定位置 
    this.scrollY = -this.listHeight[index] // 改变scrollY实时滚动的y坐标,随之改变 currentindex 高亮显示 因为向下滑动,所以为负值

}
...
function getData (el, name, value) {
  const prefix = 'data-'
  const newName = prefix + name
  if (value) { // 如果有这个值 就获取 返回
    return el.setAttribute(newName, value) // 添加自定义属性
  }
  if (!value) { // 如果没有这个值, 就设置并返回
    return el.getAttribute(newName)
  }
}
...

这里写图片描述
这里写图片描述

watch: {
    data () {
      setTimeout(() => {
        this._calculateHeight() // 监视data,计算高度,渲染数据
      }, 20)
    },
    scrollY (newY) {
      const listHeight = this.listHeight
      // 1. 当滑动到最上面
      if (newY > 0) {
        this.currentIndex = 0 // 高亮第一个元素 字母
        return
      }
      // 2. 当在中间部分滚动,length之所以 -1 是因为 为了照顾最后一个元素,当初高度列表定义必须多一个
      for (let i = 0; i < listHeight.length - 1; i++) {
        let height1 = listHeight[i]
        let height2 = listHeight[i + 1]
        if (-newY >= height1 && -newY < height2) { // newY 为负值
          this.currentIndex = i
          this.diff = height2 + newY
          return
        }
      }
      // 3. 最后一个
      this.currentIndex = listHeight.length - 2
    },
    // 实现当两个list字母碰撞时,有过渡效果
    diff (newValue) {
      let fixedTop = (newValue > 0 && newValue < TITLE_HEIGHT) ? newValue - TITLE_HEIGHT : 0
      if (this.fixedTop === fixedTop) {
        return // 判断如果两个title区块没有碰到,是不会触发 DOM 操作的
      }
      this.fixedTop = fixedTop
      this.$refs.fixed.style.transform = `translate3d(0,${fixedTop}px,0)`
    }
  },
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值