【八】listview组件

关于专题【vue开发音乐App】 何为listview?简单来说就是类似于我们手机自带的通讯录列表、音乐APP的歌手列表、外卖APP的分类菜单……,本文介绍的listview组件具备以下特性: 列表数据按照一定的分组依据(如热门、A、B、C等)进行分组后有序排列; 每组数据的顶部都有以该组名称命名的头部标签,用户滑动列表,相邻的两个头部标签之间会产生替换动画; 右侧提供快速定位的导航条,类似锚点,除简单的点击触发以外,还支持手指滑动,十分接近原生体验。 该组件实现难度较大,文章篇幅也较长,但是其中也包含了众多精彩的前端技能,所以还是希望大家能花点时间阅读本文并加以实践。 一、处理数据 数据通过jsonp跨域调用QQ音乐真实线上接口获取( 该部分不是本文重点,所以省略 ),获取到的数据是扁平的: list: [ { Farea: '1', Fattribute_3: '3', Fattribute_4: '0', Fgenre: '0', Findex: 'X', Fother_name: 'Joker', Fsinger_id: '5062', Fsinger_mid: '002J4UUk29y8BY', Fsinger_name: '薛之谦', Fsinger_tag: '541,555', Fsort: '1', Ftrend: '0', Ftype: '0', voc: '0' }, { Farea: '0', Fattribute_3: '2', Fattribute_4: '0', Fgenre: '0', Findex: 'Z', Fother_name: 'Jay Chou', Fsinger_id: '4558', Fsinger_mid: '0025NhlN2yWrP4', Fsinger_name: '周杰伦', Fsinger_tag: '541,555', Fsort: '2', Ftrend: '0', Ftype: '0', voc: '0' }, // 省略后面98个 ] 这种数据不能直接使用,需要处理成如下数据结构: list: [ { title: '热门', items: [ { id: '002J4UUk29y8BY', name: '薛之谦', avatar: 'https://y.gtimg.cn/music/photo_new/T001R300x300M000002J4UUk29y8BY.jpg?max_age=2592000' }, { id: '0025NhlN2yWrP4', name: '周杰伦', avatar: 'https://y.gtimg.cn/music/photo_new/T001R300x300M0000025NhlN2yWrP4.jpg?max_age=2592000' }, ... ] }, { title: 'A', items: [ { id: '0020PeOh4ZaCw1', name: 'Alan Walker (艾伦·沃克)', avatar: 'https://y.gtimg.cn/music/photo_new/T001R300x300M0000020PeOh4ZaCw1.jpg?max_age=2592000' }, ... ] }, ... ] 如何得到这种结构的数据?代码如下: import Singer from 'common/js/singer' const HOT_SINGER_LEN = 10 const HOT_NAME = '热门' ... _normalizeSinger(list) { let map = { hot: { title: HOT_NAME, items: [] } } list.forEach((item, index) => { // 只取前十名歌手作为热门 if (index < HOT_SINGER_LEN) { // Singer类通过歌手id可以生成avatar链接 map.hot.items.push(new Singer({ name: item.Fsinger_name, id: item.Fsinger_mid })) } const key = item.Findex if (!map[key]) { map[key] = { title: key, items: [] } } map[key].items.push(new Singer({ name: item.Fsinger_name, id: item.Fsinger_mid })) }) // 为了得到有序列表,我们需要处理 map let ret = [] let hot = [] for (let key in map) { let val = map[key] if (val.title.match(/[a-zA-Z]/)) { ret.push(val) } else if (val.title === HOT_NAME) { hot.push(val) } } ret.sort((a, b) => { // 按照“A-Z”的字母顺序排列 return a.title.charCodeAt(0) - b.title.charCodeAt(0) }) return hot.concat(ret) } Singer是抽象出来的类,作用是统一生成_normalizeSinger()方法中被push进items数组的单个歌手信息(id、name、avatar ),详细实现如下: // common/js/singer export default class Singer { constructor({id, name}) { this.id = id this.name = name this.avatar = `https://y.gtimg.cn/music/photo_new/T001R300x300M000${id}.jpg?max_age=2592000` } } 二、代码实现 src/base/listview/listview.vue: 三、调用

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):