基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)

作者 : admin 本文共9776个字,预计阅读时间需要25分钟 发布时间: 共37人阅读

1、项目开发需求分析:

包含四个层面——

(1)推荐模块

(2)歌手模块

(3)排行模块

(4)搜索模块

2、项目开发流程

(1)搭建项目:借助vue-cli脚手架工具,具体请参考博客: …;

由于项目存放在本地电脑E盘VueTest目录下,

cd E:\VueTest

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图

图1:切换项目存放目录、vue-cli搭建初始项目

通过脚手架vue-cli工具搭建项目

vue init webpack vue-music

选择配置项目相关webpack

                    

(2)进入项目vue-music

cd vue-music

安装项目node_mudules依赖(在这里采用淘宝镜像cnpm,可加快安装效率)

cnpm install

上述流程具体操作见(图2:安装项目依赖)

    基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(1)

                                         图2:安装项目依赖

在本地加载该项目工程文件

npm run dev

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(2)

                     图3:搭建成功界面

当看到localhost:8080/8081时,说明项目工程环境搭建成功。

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(3)

                                        图4:本地搭建环境成功

当显示上述界面,则表示vue-cli脚手架搭建的vue-music项目成功。

 

(3)在编辑器中打开该项目工程文件(在该环节中我采用的编辑器:VS Code)

项目目录中所以开发主要基于src目录作为主载

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(4)

图5:项目工程目录

2.3-1——目录src

api:主要存放后台请求相关的代码,包括ajax,jsonp等,

有.gitkeep文件表示虽为空,但可上传至git上

common:主要存放通用的静态资源,包括字体图标fonts、图片images、脚本文件js库、样式文件stylus

   stylus——

base.styl:基础样式,引用variable.styl

variable.styl:以“变量定义”方式引入样式文件(颜色、字体定义规范)

icon.styl:字体图标样式文件

index.styl:引入reset、base、icon三者样式文件

mixin.styl:定义一些函数,方便组件.vue文件中引用

reset.styl:重置样式文件

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(5)

图6:common目录下stylus 

components:主要存放项目中组件化.vue文件

router:主要存放静态路由相关代码index.js

store:主要存放vuex相关代码

App.vue:

main.js:主要存放渲染app文件的js脚本

 

2.3-2:更改相关文件

在build文件夹下,webpack.base.conf.js中

resolve: {
extensions: [
‘.js’,
‘.vue’,
‘.json’],
alias: {
‘src’
:
resolve(
‘src’),
‘common’
:
resolve(
‘src/common’)
}
},

 

这样,在项目中可以这么使用,如下:

import
‘common/stylus/index.styl’

 

3、页面骨架开发

(1)页面入口+header

首先,package.json文件做以下更改

 

“dependencies”: {
“babel-runtime”:
“^6.26.0”,
“vue”:
“^2.5.2”,
“vue-router”:
“^3.0.1”,
“fastclick”:
“^1.0.6”
},

 

在“devDependencis”下,新增下面babel-polyfill、stylus、stylus-loader三个依赖,

运行cnpm install

“stylus
:
“^0.54.5”,

“babel-polyfill”:
“^6.2.0”,
“stylus-loader”:
“^3.0.1”

 

(2)路由配置+顶导组件开发

router静态路由——根组件默认指向

vue-router(index.js)——new Vue({ router })(main.js)——<router-view/>(App.vue)

main.js——babel-polyfill、fastClick

 

在http://localhost:8080/#中可以用静态路由vue-router实现界面间切换

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(6)

图7:vue-router实现界面跳转

解析:由于在项目工程文件中指定根路径path:/recommend,所以默认为该界面,同时点击不同的tab选项列   表,可由静态路由进入不同的组件。

import
Router
from
‘vue-router’
Vue.
use(
Router)

 

export
default
new
Router({
routes: [
// 根组件默认的指向
{
path:
‘/’,
component:
Recommend
},
{
path:
‘/recommend’,
component:
Recommend
},
{
path:
‘/singer’,
component:
Singer
},
{
path:
‘/rank’,
component:
Rank
},
{
path:
‘/search’,
component:
Search
}
]
})

 

4、推荐模块开发

locahost:8080/#/recommend

疑难点:

a、数据获取——线上真实数据,非模拟。用qq音乐进行抓取数据,(采用jsonp进行抓取线上数据)

                       基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(7)

图8:qq音乐播放器抓取数据

b、jsonp原理:可参考github地址(https://github.com/webmodules/jsonp

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(8)

图9:github-jsonp地址

c、在index.js可查看具体实现原理

(1)Install

Install for node.js or browserify usingnpm:

$ npm install jsonp

Install for component(1) using component:

$ component install LearnBoost/jsonp

Install for browser using bower:

$ bower install jsonp

 

(2)API

jsonp(url, opts, fn)

  • url (String) url to fetch
  • opts (Object), optional
    • param (String) name of the query string parameter to specify the callback (defaults to callback)
    • timeout (Number) how long after a timeout error is emitted. 0 to disable (defaults to 60000)
    • prefix (String) prefix for the global callback functions that handle jsonp responses (defaults to __jp)
    • name (String) name of the global callback functions that handle jsonp responses (defaults to prefix + incremented counter)
  • fn callback

操作——在package.json下定义jsonp,再cnpm install安装该依赖

“dependencies”: {
“babel-runtime”:
“^6.26.0”,
“vue”:
“^2.5.2”,
“vue-router”:
“^3.0.1”,
“fastclick”:
“^1.0.6”,
“jsonp”:
“^0.2.1”
},

 

jsonp的封装“./src/common/js/jsonp.js”

 

// jsonp封装(用promise实现封装)
import
originJSONP
from
‘jsonp’

 

export
default
function
jsonp(
url,
data,
option) {
// url拼接
url += (
url.
indexOf(
‘?’) <
0 ?
‘?’ :
‘&’) +
param(
data)
// Promise()回调函数,类似于callback,三种状态:pending(进行中)/resolve(已完成)/reject(已失败)
return
new
Promise((
resolve,
reject)
=> {
originJSONP(
url,
option, (
err,
data)
=> {
if (!
err) {
resolve(
data)
}
else {
reject(
err)
}
})
})
}

 

// 将data转换为json格式
function
param(
data) {
let
url =
for (
var
k
in
data) {
let
value =
data[
k] !==
undefined ?
data[
k] :
url +=
`&
${
k
}
=
${
encodeURIComponent(
value)
}
`
}
return
url ?
url.
substring(
1) :
}

 

jsonp使用:对其以promise方式封装,同时在/api目录下封装获取数据的方法

 

(1)轮播图

4.1-1数据抓取

components——recommend.vue“slide-wrapper”

api——recommend.js、config.js

js——jsonp.js

当上述文件编译成功,在开发者工具F12下的console控制台程序,会显示如下:

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(9)

图10:qq音乐轮播图数据抓取成功界面

4.1-2:轮播图组件开发

目录base基础目录——src/base/slider/slider.vue,

slot插槽<slot></slot>

<
div
class=
“slider”
>
<!– slotA与slotE有什么区别 –>
<
div
class=
“slider-group”
>
<
slot
></
slot
>
</
div
>

 

<
div
class=
“dots”
>

 

</
div
>
</
div
>

 

轮播图模块实现:

   实现方式很多,在这里借助better-scroll库实现Slider组件开发

   属性:snap——false,针对slider开发,普通列表滚动不需要配置

         snap——false 是否可以无缝循环轮播

 snapSpeed——400,轮播图切换的动画时间

4.1-2-1:slider-group(轮播图横向点击无缝滚动)

a、初始化Scroll

首先,在package.json中安装依赖,并在命令行中执行“cnpm install”

“dependencies”: {
“better-scroll”:
“^1.4.2”,
}

其次,在slider.vue组件中引入该库

import
BScroll
from
“better-scroll”

 

b、计算setSliderWidth,在methods方法中,定义_setSliderWidth()

// 设置轮播宽度
_setSliderWidth() {
// 获得列表元素多少
this.
children =
this.
$refs.
sliderGroup.
children

 

// 设置宽度/每个slider宽度均为元素的clientWidth
let
width =
0
let
sliderWidth =
this.
$refs.
slider.
clientWidth
for(
let
i=
0;
i<
this.
children.
length;
i++) {
// 先获取每个子元素
let
child =
this.
children[
i]
// import addClass方法,并传入参数
addClass(
child,
‘slider-item’)
// 设置每个child的宽度
child.
style.
width =
sliderWidth +
‘px’
width +=
sliderWidth
}

 

// loop需要克隆2倍宽度
if(
this.
loop) {
width +=
2*
sliderWidth
}
this.
$refs.
sliderGroup.
style.
width =
width +
‘px’
},

 

c、初始化轮播图slider,methods中_initSlider()方法,此时引用a中BScroll插件

// 初始化轮播图
_initSlider() {
// 绑定DOM元素slider,options配置
this.
slider =
new
BScroll(
this.
$refs.
slider, {
// 只允许横向滚动,不允许纵向
scrollX:
true,
scrollY:
false,
momentum:
false,
// 惯性
snop:
true,

//无缝滚动

snopLoop:
this.
loop,
snopThreshold:
0.3,
snopSpeed:
400,
click:
true
})
}

 

4.1-2-2:dots设置自动轮播

为了实现该功能,必须在初始化initSlider()之前初始化dos,

首先,在data()中定义一个dots对象

data() {
return {
dots: []
}
},

 

其次,在methods方法中定义_initDots()

// 初始化dots
_initDots() {
this.
dots =
new
Array(
this.
children.
length)
},

 

最后,在mounted钩子里调用该方法,在_initSlider()之前

// mounted钩子
mounted() {
setTimeout(()
=> {
this.
_setSliderWidth()
this.
_initDots()
this.
_initSlider()
},
20);
},

 

测试:当不清除定时器时,由于在自动播放autoPlay()之前,为手动播放,所以需要清除clearInteral()

// 给slider绑定scrollEnd()事件() => {}回调函数
this.
slider.
on(
‘scrollEnd’, ()
=> {
// 表示第几个子元素
let
pageIndex =
this.
slider.
getCurrentPage().
pageX
if(
this.
loop) {
pageIndex -=
1
}
this.
currentPageIndex =
pageIndex

 

// 测试:由于上述代码运行只滚动一次,所以该事件scrollEnd有bug,对其添加autoPlay进行测试
if(
this.
autoPlay) {
// 由于在自动播放的时候,是手动播放,所以需要clear定时器
clearInterval(
this.
timer)
this.
_play()
}
})

 

运行效果图如下:(注意:可以自动播放,截取的是静态图)

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(10)

优化: 当发现在控制台上切换不同的屏幕大小的时候,界面显示出现错误,如下:

基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(11)

 

解析:上述bug出现的主要原因是因为_setSliderWidth()中sliderWidth出现了小问题,即window下的resize

解决办法:监听一个window下resize事件

// 优化sliderWidth宽度不一的问题
window.
addEventListener(
‘resize’, ()
=> {
// 当slider未初始化
if(!
this.
slider) {
return
}
// 判断是否有isResize(),
this.
_setSliderWidth(
true)
// 宽度发生变化,需要重新计算刷新以下slider
this.
slider.
refresh()
})

 

此外,在_setSliderWidth()事件,应该传入参数isResize做判断,同时执行函数时,初始下不需要isResize(),但到重新计算宽度时,就不能width*2

// 若loop自动播放为true,且不需要resize时,loop需要克隆2倍宽度
if(
this.
loop && !
isResize) {
width +=
2*
sliderWidth
}

 

重新编译后,会发现无论是在移动端进行测试,还是切换屏幕大小,在pc或Mac端测试,宽度均不会出现问题,

但是,当我们重新切换或者加载的时候,recommend.vue生命周期,以及相关数据均会重新加载一遍才会刷新到数据,导致体验差,

优化1:App.vue中,将router-view加一个keep-alive进行dom缓存

<
keep-alive
>
<
router-vxew
></
router-view
>
</
keep-alive
>

 

优化2:slider.vue中,export default({})加一个destroyed()清除缓存定时器

// destroyed生命周期,当存在寄存器,元素销毁时机,清除资源
destroyed() {
clearTimeout(
this.
timer)
}

 

4.1-3:歌单列表组件开发

a、歌单数据接口分析

在这里抓取的是PC端歌单数据,地址:https://y.qq.com/portal/playlist.html

               基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)插图(12)

从上述console控制台下NetWork  general下的requestUrl即为表单数据接口地址

https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg

 

b、实现原理

首先,定义接口获取函数。包括url以及data相关数据,在recommend.js

 

// 获取歌单接口数据
export
function
getDiscList() {
// 歌单接口url地址
const
url =
‘https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg’

 

// 定义表单接口数据
const
data =
Object.
assign({}.
commonParams, {
platform:
‘yqq’,
hostUin:
0,
needNewCode:
0,
categoryId:
10000000,
sortId:
5,
sin:
0,
ein:
29,
rnd:
Math.
random()
})

 

return
jsonp(
url,
data,
options)
}

 

其次,在recommend.vue组件下调用该获取接口数据函数

 

created() {
// 获取轮播图图片接口数据函数
this.
_getRecommend(),
// 获取歌单接口数据函数
this.
_getDiscList()
},

 

同时,在表头引入该函数

 

import {
getRecommend,
getDiscList}
from
‘api/recommend’

 

c、后端接口代理axios

  由于若使用jsonp进行数据抓取,会导致一些错误,因为qq音乐服务器端不会识别,只能在项目build目录下dev-server.js下,配置与qq音乐相同的headers——referer、host相同,这样服务器端识别完成,相当于后端代理的方法获取了后台的歌单接口数据。

 

  采用ajax http请求API axios库https://github.com/mzabriskie/axios

首先,package.json上写入axios,并在cmd命令行cnpm install安装依赖

 

“dependencies”: {
“axios”:
“^0.17.1”
},

 

在build/dev-server.js中中,设置Axios后端接口代理,用于获取接口数据,再进行调取相应的api。

 

const
axios =
require(
‘axios’)
const
app =
express()

 

// define apiRoutes
const
apiRoutes =
express.
Router()

 

// 后端接口代理
apiRoutes.
get(
‘/getDiscList’,
function(
req,
res) {
// ajax库axios
const
url =
‘https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg’
axios.
get(
url, {
headers: {
referer:
‘https://c.y.qq.com/’,
host:
‘c.y.qq.com’
},
params:
req.
query
}).
then((
response)
=> {
res.
json(
response.
data)
}).
catch((
e)
=> {
console.
log(
e)
})
})

 

app.
use(
‘/api’,
apiRoutes)

 

 

未完待续…(由于axios请求接口一直处于404失败状态,所以recommend组件结合dev.server.js配置未达到预期的效果,还需要做到后期的改善)

 

4.1-4:scroll滚动组件,scroll.vue

  由于scroll滚动适用于所有模块界面的滑动,所以作为一个组件进行开发,结合slot插槽进行使用

 

<
template
>
<
div
ref=
“wrapper”
>
<
slot
></
slot
>
</
div
>
</
template
>

  在<script/>文件主要用于设置文件所需的脚本渲染,包括import、export模块的引入,再加上属性之间的渲染,

 

methods: {
// 定义一个初始化scroll的方法,在mounted()中使用
_initScroll() {
if(!
this.
$refs.
wrapper) {
return
}
this.
scroll =
new
BScroll(
this.
$refs.
wrapper, {
probeType:
this.
probeType,
click:
this.
click
})
},

 

// 若存在即调用enable()
enable() {
this.
scroll &&
this.
scroll.
enable()
},
// 否则调用disable()
disable() {
this.
scroll &&
this.
scroll.
disable()
},
// 刷新scroll重新定义高度
refresh() {
this.
scroll &&
thid.
scroll.
refresh()
}
},

 

初始化完_initScroll()方法后,需要在mounted()函数中使用,

 

// 钩子函数
mounted() {
setTimeout(()
=> {
this.
_initScroll()
},
20)
},

 

其次,采用watch进行监听数据data变化

 

// 监听器
watch: {
data() {
setTimeout(()
=> {
this.
refresh()
},
20)
}
}

 

4-3:图片懒加载

与图片“延迟加载”的js、jq实现原理一致:

1 设置一个定时器,计算每张图片是否会随着滚动条的滚动,而出现在视口(也就是浏览器中的 展现网站的空白部分 )中;

2 为<img>标签设置一个暂存图片URL的自定义属性(例如loadpic),当图片出现在视口时,再将loadpic的值赋给图片的src属性;

 

优点:(1)节省流量

      (2)提升加载速度

引用第三方插件:vue-lazyload插件

  https://github.com/523451928/vue-lazyload

 

使用方法

  • 1、直接页面引用vue-lazyload.js(注意我自己使用的vue-cli,所以在js文件里面最后导出了Lazyload),页面引用需要删除export default Lazyload
  • 2、用脚手架import js文件

html 部分:

<img :imgsrc="url"/>

JS 部分:

  1. //vue-cli
  2. import Lazyload from ‘vue-lazyload.js’
  3. Vue.use(Lazyload)
  4. //页面直接引用
  5. Vue.use(Lazyload)
  6. this.$lazyload({
  7.    elm:document.querySelector(),   //需要懒加载的图片集合 (默认所有图片)
  8.    src:“imgsrc”,               //给img标签加的属性为图片的地址 (默认imgsrc)
  9.    threshold:100, //提前加载距离  (默认100px)
  10.    opa:0.3,   //图片初始透明度 (默认0.3)
  11. duration:1.5, //过渡时间
  12.    loadImg:     //加载之前显示的load图片的路径
  13. })

 

import
VueLazyLoad
from
‘vue-lazyload’
Vue.
use(
VueLazyLoad, {
loading:
require(
‘common/image/default.png’)
})

 

 


滴石it网-Java学习中高级和架构师教程_Java企业级开发项目实战下载 » 基于Vue2.x开发的音乐播放器app(推荐界面+懒加载+axios获取后端接口实现)

常见问题FAQ

发表回复

开通VIP 享更多特权,建议使用QQ登录