前言


通过github拉取下的后台服务器,根据接口文档,调用真实的网易云音乐数据,独立开发而成,收获很多 完成了 :

  • 每日推荐的歌曲,歌单,视频页面,账号登陆的展示数据信息功能
  • 歌曲和视频的播放切换,进度条实时跟进功能
  • 视频区下拉刷新,模糊搜索歌曲功能

开发完成后最大的感受就是一定要会看,会查微信小程序的官方API文档,出bug时首先检查语法是否正确(刚入门比较容易犯拼写错误),根据控制台给错的错误信息定位到相应文件,进行逻辑检查,注意后端返回的数据类型和和格式转换,看清接口文档明白后端要接收到的实际参数!!

  • 微信小程序官方文档
  • 网易云接口调用文档
  • 视频演示
  • 源码

页面预览:

功能介绍:获取诸如每日推荐的静态数据

诸如上述的每日轮播图,歌曲,歌单数据,获取方式十分简单,只需要参考调用文档,发送GET数据请求,解析收到的数据,将需要的信息展示到预先设好的图片插槽上即可。

在相应模块中的js文件里设置存放诸如每日轮播图,歌曲,歌单数据的数组

 data: {// 轮播图数据bannerList: [],// 精心推荐歌单数据recommendList: [],// 排行榜数据topList: [],},

然后在onLoad声明周期函数中,调用接口(注意文档所要求携带的参数),获取数据,将接口返回的数据通过setData方法保存至刚设置的数组里。

 onLoad: async function (options) {let bannerListData = await request('/banner', { type: 2 });this.setData({bannerList: bannerListData.banners})// 获取推荐歌单数据let recommendListData = await request('/personalized', { limit: 10 });this.setData({recommendList: recommendListData.result})// 获取排行榜的数据let index = 0;let resultArr = [];while (index < 5) {let topListData = await request('/top/list', { idx: index++ });let topListItem = { name: topListData.playlist.name, tracks: topListData.playlist.tracks.slice(0, 3) }resultArr.push(topListItem);this.setData({topList: resultArr})}},

最后通过插槽展示出来,对于一些组件,可以添加官方给出的样式属性,让布局的交互效果更佳。

 <!-- 轮播图区域 添加的属性:自动播放,切换时间间隔,下方小圆点 --><swiper autoplay interval="4000" class="banners" indicator-dots="true" indicator-color="ivory" indicator-active-color="#d43c33"><swiper-item wx:for="{{bannerList}}" wx:key="bannerId"><image src="{{item.pic}}"></image></swiper-item></swiper>

推荐歌曲部分大抵如此:

 <!-- 推荐歌曲内容区 --><scroll-view class="recommendScroll" enable-flex scroll-x><view class="scrollItem" wx:for="{{recommendList}}" wx:key="id" wx:for-item="recommendItem"><image src="{{recommendItem.picUrl}}"></image><text>{{recommendItem.name}}</text></view></scroll-view>

榜单部分:这里以item项进行滑动,每个item项宽度固定,只需调节宽度大小即可控制下一item项在页面的显示位置。

    <swiper class="topListSwiper" circular next-margin="110rpx"><swiper-item class="swiperBack" wx:for="{{topList}}" wx:key="name"><view class="title">{{item.name}}</view><view class="musicItem" wx:for="{{item.tracks}}" wx:key="id" wx:for-item="musicItem"><image src="{{musicItem.al.picUrl}}"></image><text class="count">{{index + 1}}</text><text class="musicName">{{musicItem.name}}</text></view></swiper-item></swiper>

功能介绍:用户登陆

整个流程大致为:

  1. 前端验证

    1. 实时收集用户输入框数据(给账密绑定 id ,通过事件委托实时存储用户输入值)
    2. 验证账号密码是否合法(验证是否为空,格式正确,长度这几种情况)
    3. 验证通过就将账密发个请求给客户端,反之不通过则提示用户,不用发请求
  2. 后端验证
    1. 调用数据库验证用户是否存在
    2. 用户存在即验证密码是否正确,跟下一步一样,账密任何一个输错停止下一步,并告诉前端**错误
    3. 都正确就返回用户的数据给前端,并提示登陆成功

在实时存储和验证用户输入的账号密码时用的是同一个处理函数,怎么却分他们谁是谁呢,一般用id进行区别。这里有个重要知识点:事件委托。事件委托就是把子元素的事件让父元素完成,可通过event.target 找到触发的子元素,currentTarget 要求绑定事件的元素一定是触发事件的元素。

根据id存储信息

let type = event.currentTarget.dataset.type;this.setData({[type]: event.detail.value})

点击登陆,携带账号密码信息触发后端验证(状态码为:200通过,400手机号错误,502密码错误),wx.showToast 显示登陆情况。成功后 wx.setStorageSync 将用户信息保存到本地(存储为json字符串格式类型),接着 reLaunch 重定向到某页面。

wx.setStorageSync('userInfo', JSON.stringify(result.profile))
wx.reLaunch({url: '/pages/personal/personal'})

功能介绍:视频播放

网易获取视频需要用户登陆,用户登陆后把保存在本地的cookies取出。因为项目是做成上边导航栏,下边根据导航栏的索引 id 获取相关视频的开发模式,所以先获取导航栏的数据,和标签id分别以数组的形式存放在data数据中。

获取导航栏数据方式跟先前拉取静态歌曲方式一样,均通过异步请求,来获取保存显示数据。不过这里有些不同,官方给的导航api中,标签id不能以数字开头,所以在显示时,均加以 ”scroll“ 字符串来满足要求,

<!-- 视频导航栏区域 --><view id="{{'scroll' + item.id}}" class="navItem" wx:for="{{videoGroupList}}" wx:key="id"><view class="navContent {{navId === item.id?'active': ''}}" bindtap="changeNav" id="{{item.id}}" data-id="{{item.id}}">{{item.name}}</view></view>

默认是第一个标签页视频,在点击第一个导航栏标签时,会将上面的字符串更改为数值类型,同时初始化该变迁下的存储视频数组,接着携带id触发获取视频调用函数。因为获取的视频里,单个视频没有唯一的id,所以我需要用map加工一下

  async getVideoList (navId) {if (!navId) { // 判断navId为空串的情况return;}let videoListData = await request('/video/group', { id: navId });// 关闭消息提示框wx.hideLoading();let index = 0;let videoList = videoListData.datas.map(item => {item.id = index++;return item;})this.setData({videoList,isTriggered: false // 关闭下拉刷新})},

到这里,视频获取就算完成额了,但是存在一些小问题。比如:同时播放多个视频。不能对视频进行上一次播放进度的跟踪。

解决多个视频同时播放的问题(单例模式)和回到上个视频的播放进度

单例模式主要思想:在多个对象的场景下,通过一个变量接收,始终保持只有一个对象。那么用户在播放第二个视频时,我们需要通过上述map生成的唯一id判断这俩者不是同一个视频。

回到上个视频的播放进度的整体思路是:当我们每点击一个视频,存储该视频id,创建一个事件对象,

 let vid = event.currentTarget.id;this.setData({videoId: vid})this.videoContext = wx.createVideoContext(vid);

查看他是否有播放记录,有就跳转到指定位置,没有就重头开始播放,然后实时将记录存储到刚创建的对象里的记录播放时长属性中。

 // 判断当前的视频之前是否播放过,是否有播放记录, 如果有,跳转至指定的播放位置let { videoUpdateTime } = this.data;let videoItem = videoUpdateTime.find(item => item.vid === vid);if (videoItem) {this.videoContext.seek(videoItem.currentTime);}

关于播放时长的回调,播放前需判断播放时长是否有值,有就覆盖,在播放。

if (videoItem) { // 之前有videoItem.currentTime = event.detail.currentTime;} else { // 之前没有videoUpdateTime.push(videoTimeObj);// 有bugthis.videoContext.play();}// 更新videoUpdateTime的状态this.setData({videoUpdateTime})

再有就是视频播放完后,需要善删掉视频播放状态

videoUpdateTime.splice(videoUpdateTime.findIndex(item => item.vid === event.currentTarget.id), 1);

下拉刷新,重新根据标签id发数据请求:上拉同理

  handleRefresher () {// 拿到数据后更改控制回弹属性是否为false即可this.getVideoList(this.data.navId)},


功能介绍:音乐播放

界面预览:

上面的日期采用 date.getMonth() 来定义进行实时显示,歌曲部分除付费歌曲外,都能通过接口调用获取。获取前需要验证用户是否登陆,通过先前登陆存储在本地的 userInfo 进行判断,没登陆即 reLaunch 到 login 页面。

这里稍提一下图像文本居中排布问题:
例如左侧图片,右侧文字需要做到居中对其、文本框内图标,与默认文字对其的情况。
根据子绝父相设置定位,接着父子元素都要设置 flex 弹性布局。每首歌曲是一个item项目,给图片设置宽高圆角底边距后(不用设浮动),右侧的文字也将看作是一个item,设置flex,和经典居中三命令执行。

.musicInfo text{height: 40rpx;line-height: 40rpx;font-size: 24rpx;white-space: normal;overflow: hidden;text-overflow: ellipsis;
}

最右侧图标利用绝对定位加边距调整即可;图标在搜索框中与文字齐平,图标可用 vertical-align 来设置center值。

居中排版问题说完,继续说音乐播放相关的事。

音乐暂停播放键的显示
对暂停还是播放的图标有俩个类名来取决显示那个图标,默认暂停(isplay:false),设置isPlay属性,没点一次通过 setData() 对 isplay 进行取反更新操作。

点击歌曲后跳转到播放页面获取详情信息
点击歌曲后,需要携带所点击的歌曲的名称,id信息发送到播放页面

url: '/songPackage/pages/songDetail/songDetail?musicId=' + song.id

播放页面那边接受id发送请求获取该歌曲详情信息,其中durationTime为已播放时长。

 // 获取音乐功能详情的功能函数async getmusicInfo (musicId) {let songData = await request('/song/detail', { ids: musicId });let durationTime = moment(songData.songs[0].dt).format('mm:ss');this.setData({song: songData.songs[0],durationTime})wx.setNavigationBarTitle({title: this.data.song.name})},

播放或暂停音乐
播放一首歌曲,需要知道该播放或暂停键的isPlay状态,音乐id,和该音乐的链接地址,音乐的链接地址可通过id向接口发送请求获取。

小问题:当播放一首歌退出界面在点进来,会重头播放
这时只需判断全局下的播放状态为真和id等于现在点的这首歌id就改变播放按钮状态即可,相同则不做播放处理。

if (appInstance.globalData.isMusicPlay && appInstance.globalData.musicId === musicId) {this.setData({isPlay: true})}

上一首或下一首切换
给上一首或下一首分别绑定id值,但用统一处理事件,用户点击时连同id值一起传入,通过播放事件判断是上一首还是下一首,上一首的话就把当前歌曲id所在每日推荐的位置减一进行播放,反之+1。
点击的同时需要暂停当前播放曲目,

  handleSwitch (event) {let type = event.currentTarget.id;// 点以下一首后关闭当前音乐this.backgroundAudioManager.stop();// 定于recommend的页面数据PubSub.subscribe('musicId', (msg, musicId) => {// 拿到id后切换上下一首的歌曲详情信息,在调用是否播放函数this.getmusicInfo(musicId);this.musicControl(true, musicId);// 拿到id后在取消订阅,因为订阅依赖回调,会累加PubSub.unsubscribe('musicId')})// 发布消息给recommend页面PubSub.publish('switchType', type)},
PubSub.subscribe('switchType', (msg, type) => {let { recommendList, index } = this.data;if (type === 'pre') {(index === 0) && (index = recommendList.length)index -= 1;} else {(index === recommendList.length - 1) && (index = -1)index += 1;}this.setData({index})let musicId = recommendList[index].id;PubSub.publish('musicId', musicId)});

遇到的问题

导航元素id类型转换问题:

let navId = event.currentTarget.id;再点击导航栏获取元素id,想给他动态添加下标样式时,发现不成功,打印id发现拿到的元素是字符型的,而数据项中的id应该是数值,所以索引不到对应的item元素项。
解决方法:在更新数据时,把id*1转成数值型就好,或者位移运算符>>> 0,或者在获取方式改为:let navId = event.currentTarget.dataset.id

视频播放:
每点击一个视频就通过createVideoContext创建一个事件对象,在data中保存视频的数据列表,id,还有记录视频的播放时长videoUpdateTime。点击的时候,更新data中的视频id,接着监听进度条(videoUpdateTime以对象的形式存视频id和进度时间,如果查询到有这个视频id的记录,就seek,没有就push添加记录,然后play播放)判断视频是否播放过,来决定是否跳转(videoContext.seek)到相应进度条。

下拉刷新:
在handleRefresher生命周期中重新发起一个该导航栏下的数据请求即可。

视频第一帧:
给video加上poster="{{item.data.coverUrl}}"属性,image部分加载,通过判断上一个视频播放的id和当前视频id是否一致决定加载的是视频还是图片。点击图片触发的播放回调函数跟视频的一致。

做的优化

问题:点击歌曲的时候,不知道歌曲有无请求过,每次都是发送请求播放。

优化内容:将歌曲地址进行存储,播放时判断有无链接,有就通过backgroundAudioManager.src= musicLink调用进行播放,没有就重新发送,减少后台请求次数。


还会继续开发,计划完善

  • 各类歌单功能:点击歌单,跳转到歌单列表,再点击歌曲,进行播放
  • 显示歌曲的歌词,应该有现成的库可直接调用
  • 显示歌曲评论,完成歌曲的交互功能
  • 根据搜索名称得到单曲,歌单,mv之类的数据

呃呃呃,,,差不多这样

仿网易云音乐的小程序项目(粗糙版)相关推荐

  1. 仿网易云音乐微信小程序源码

    欢迎star issue 仿网易云音乐APP的微信小程序 源码下载地址,自己去下载就行,http://code.662p.com/view/19352.html 目前实现功能 用户 歌单 FM 播放 ...

  2. 尚硅谷微信小程序开发 仿网易云音乐App 小程序 后端接口服务器搭建

    目录 小程序学习 视频相关的教程文档与笔记分享 配套服务器 源码地址: 接口使用说明文档 接口列表 启动服务 测试服务启动OK网页 http://localhost:3000/test.html​编辑 ...

  3. 网易云音乐微信小程序 毕业设计

    本期我们将讲解网易云音乐微信小程序. 之前我已经讲过网易云音乐小程序的旧版本.现在是全新的版本,涉及的功能点非常多.接下来,我们将对这个项目进行详细介绍. 首先,我们来看整个网易云音乐小程序的主页,也 ...

  4. 计算机毕业设计Node.js+Vue安卓仿网易云音乐客户端APP(程序+源码+LW+部署)

    该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程.欢迎交流 项目运行 环境配置: Node.js+ Vscode + Mysql5.7 + HBuilderX+Navicat11+Vue ...

  5. [干货教程]仿网易云课堂微信小程序开发实战经验

    本篇文章想跟大家分享下:我们公司"湖北诚万兴科技"最近刚帮客户定制开发.目前已上线的"哎咆课堂"微信小程序的开发经验分享.首先大概介绍下这个小程序所涉及到的主要 ...

  6. 仿网易云音乐(微信小程序版)

    项目部分截图(Gif) 前言 前一阵子学习了微信小程序,为了巩固所学的知识和提高实战经验,决定自己手撸一款小程序.因为听歌一直在用网易云音乐,所以突发奇想就做一款仿网易云音乐的小程序吧!开发中遇到了很 ...

  7. 微信小程序仿网易云音乐(使用云开发,提供源码)

    微信小程序仿网易云音乐(使用云开发,提供源码)!!!!!!!!!!! 源码: 链接:https://pan.baidu.com/s/1z_ZnRVbT4vjEENimi8yBQQ 提取码:u0o3 一 ...

  8. 新版仿网易云音乐的YY音乐微信小程序源码

    正文: 仿网易云音乐的YY音乐微信小程序源码,这是一款仿网易云手机端的小程序源码 名为YY音乐小程序,首页有每日推荐歌曲.歌单和热歌排行榜,功能不是特别多 但是还是比较简洁美观的,省去了现在网易云音乐 ...

  9. 高仿网易云音乐UI的微信小程序源码

    简介: 仿网易云音乐的微信小程序源码,名为YY音乐小程序,首页有每日推荐歌曲.歌单和热歌排行榜,功能不是特别多但是该有的都有. UI特别精致,简直就是克隆的网易云音乐. 源码下载:百度网盘自取 图片:

最新文章

  1. 如何实现一个连接池?一文带你深入浅出,彻底搞懂!
  2. SAP MM MB1C + 523 移动类型的使用
  3. webstorm快捷键生成html页面,webstorm工具使用的快捷键
  4. 怎么在电脑上使用python3.6_Windows下 Python3.6.1 运行环境的搭建
  5. Linux负载均衡Nginx六种策略
  6. CodeForces - 765D Artsem and Saunders(数学化简+构造+思维)
  7. php基础 简书,PHP入门基础
  8. echo “1“ > /proc/sys/net/ipv4/ip_forward(数据包转发)
  9. 两个分数化简比怎么化_怎么化行最简形矩阵?
  10. Python的第三方库xlrd
  11. 牛客题霸-SQL篇——1~10题
  12. MySql数据导入导出及解决ERROR2006(MySQL server has gone away)错误
  13. Atitit.分区对索引的影响 分区索引和全局索引 attilax总结
  14. macbook 安装mysql_mac下安装mysql
  15. matlab/simulink中带参数的S-Function(S函数)的写法
  16. VINS-Mono 代码详细解读——回环检测与重定位、四自由度位姿图优化
  17. python substract_Python layers.Subtract方法代码示例
  18. BATMAN-ADV
  19. 怎么卸载apowerrec_Win10怎么卸载预装软件 Win10卸载预装应用教程
  20. 数据存在内存里的格式是什么?

热门文章

  1. 西门子1200plc485轮询读写28个测试仪表,包括plc程序和触摸屏程序
  2. 微信开发之使用第三方图文编辑器
  3. Chrome浏览器自带翻译功能不能使用了?看我的解决方法
  4. 嵌入式C语言编程规范
  5. 基站定位和GPS定位区别
  6. 局域网内设置共享打印机并连接使用
  7. java web分层和层间数据传递 vo bo po
  8. 如何看待人生与技术的价值
  9. 电脑端使用文件微信聊天记录的本机/新机备份迁移
  10. 使用谷歌、360浏览器的F12功能模拟微信访问网页