歌手页面开发
歌手数据接口抓取
singer.js
|
|
singer.vue获取数据
|
|
处理数据
获取到的数据发现并不是我想要的数据结构,那怎么处理请求获取到的数据?
思路:把歌手数据分做为两层数组,外层是ABCD为区分歌手的数组,另一层则是以字母为首相关的歌手(比如以A为首字母的歌手)的二级数组。Findex
标识为ABCD,它是随机的,也没有热门的歌手数据。这里我把Findex
做聚合,把相同的归类起来,其次把前10条数据作为热门数据提取出来,这样可以得到我想要的数据结构。
|
|
歌手列表 — 滚动列表组件开发
列表组件也可以在其他地方使用,所以把它作为基础组件增加它的通用性。
listview.vue
|
|
引入singer.vue组件并渲染到页面上,同时实现列表滚动。
还有两个部分:右侧快速入口、滚动的时候会有固定的字母(title)显示列表上方
右侧快速入口
右侧快速入口实际上就是以字母开头的title。首先构造一个可以被遍历的数组数据。
获取右侧快速入口的列表
|
|
实现左右侧的交互(右侧栏滚动事件)
@touchstart
点击事件
显示右侧入口栏仅仅是个dom,并没有其他交互行为。新建@touchstart
点击事件,点击这个事件后滚动到相应的元素,那就要先知道滚到第几个元素才能知道左侧第几个组(group),所以点的时候要获取到这个元素的索引,获取索引:data-index="index"
。
|
|
@touchMove
事件
实现点击鼠标拖动右侧栏左侧歌手也跟着滚动到相应位置,监听@touchMove
事件。要知道从touchstart到touchMove滚动的位置,计算当前位置和一开始滚动位置的差来算出滚动到第几个元素。在touchstart的时候记录当前的y值y1(firstTouch.pageY
),然后在touchMove的时候又获取touch到的y值y2。
要有一个属性保存firstTouch的pageY位置,为了方便在两个函数之间相互获取这个数据,在created定义个touch对象(我们并不需要观测touch的变化,所以这里在created里定义)。
>
@touchmove.stop.prevent
的stop是为阻止事件向上冒泡。
|
|
左右联动
根据左侧滚动右侧也滚动到相应的位置,同时滚动的位置字母显示高亮。比如滚动到C位置的时候C为高亮显示。
想要左右联动的话,首先必须知道当前滚动的时候右侧知道滚动的位置,要有一个变量记录滚动的位置也就是y轴的位置,根据实时滚动的位置计算我的位置落在哪个区间,所以要实时监听y轴的位置。这里要对scroll组件做一些拓展。
scroll.vue
|
|
这里不需要关心它的滚动位置,所以default设置为false,如果是true的话,在初始化scroll的时候要加个逻辑,监听scroll的滚动事件从而触发scroll事件,这样就可以拿到它的位置,pos是个对象,包含x轴和y轴的属性。
在listview组件里实现滚动事件
定义两个观测数据:
scrollY:记录实时滚动的位置
currentIndex:当前显示的位置(currentIndex对应哪个谁谁就高亮)
|
|
要知道scroll落在哪个位置,首先这个列表的每个group都有高度,先计算每个group的高度。当data发生变化的时候要延迟计算它的高度,这里还要watch data的变化。
|
|
有了listHeight,就方便观察scrollY变化时,scrollY和listHeight做对比就知道它落在第几个区间,从而就得到currentIndex。
观测scrollY
|
|
滚动时出现问题,发现监听不到在swipe的情况下的scroll事件,想要监听这种实时滚动的话就不截流这种方式,需要改变probeType的值,默认是1改成3。
probeType:
1
滚动的时候会派发scroll事件,会截流。2
滚动的时候实时派发scroll事件,不会截流。3
除了实时派发scroll事件,在swipe的情况下仍然能实时派发scroll事件
有了currentIndex,需要右侧栏有个active的效果,效果如图:
当滚动到最底部的时候newY的值是大于0的,值就为负数它就永远不会落到这个区间。我们可以拆分为三种情况:歌手列表滚动到最顶部时、中间时和最底部时,最顶部时newY是大于0的,最底部时newY可能大于height2,也就是说newY值可以大于最后一个元素的上限。这样就可以在什么情况下应该怎么计算currentIndex,保证实时滚动currentIndex能计算出应该落到的位置。
对watch scrollY做些相应的改变:
|
|
当点击右侧快速入口时可以切换左侧的位置,但是高亮并没有随之改动,是因为高亮并不是根据点击的位置,而是根据scrollY计算而来的,scrollY的变化又是根据scroll事件实时更新的,调用_scrollTo(index)
方法让它滚动到相应的位置,但是这个滚动并没有触发滚动事件,所以监听不到scrollY的变化,需要手动去改变scrollY的值。
|
|
优化
解决右侧栏边界问题
为了页面好看右侧栏的上下两头分别多出一些边缘,但是这两个边缘点击是无意义的,不会触发任何滚动事件,做些逻辑处理。
|
|
解决右侧栏滑动到最顶部直接跳到底部的问题
console.log(index)
发现滑动到最顶部是负值,最底部是无限大的值,是因为touchmove
一直在执行,它的y值一直在变大,同样anchorIndex
的值也变超。对于滑动顶部或底部做些边界条件处理。
|
|
滚动固定标题实现(fixed-title)
fixed-title:当我们滚动到某个区块,列表顶部会显示对应的名称,其实和右侧显示高亮有异曲同工之妙,不同的是dom实现不一样。
|
|
|
|
当滚动时左侧列表顶部需要有一个fixed-title,当两个title重合的时候要有一个title往上顶的效果,在data里定义一个diff。diff表示滚动到的区块的上限和当前滚动位置的滚动差。
观测scrollY做些改变:
观测diff的变化来设置fixed-tit1e的偏移。
|
|
歌手列表是异步获取的,这里也要使用loading效果,listview里引入loading组件
|
|
总结:
左右联动思路:想要达到左右联动,首先需要实时知道滚动位置,根据滚动位置计算出当前位置是落到哪个group的区间,相应的算出右边哪个索引应该高亮,结合vue的watch观测数据变化。