vue 音乐app项目7 歌单及排行榜开发

前言:以下内容均为学习慕课网高级实战课程的实践爬坑笔记。

项目github地址:https://github.com/66Web/ljq_vue_music,欢迎Star。

歌单及详情页 排行榜及详情页
一、歌单详情页开发
歌单详情页布局介绍及Vuex实现路由数据通讯

components->disc目录下:创建disc.vue
router->index.js中:给Recommend添加二级子路由Disc
{
path: ‘/recommend’,
component: Recommend,
children: [
{
path: ‘:id’,
component: Disc
}
]
}
recommend.vue中:
添加路由容器

给歌单列表添加点击事件
@click=“selectItem(item)”
定义selectItem()实现路由跳转
selectItem(item) {
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …h: `/recommend/{item.dissid}`
})
}
使用vuex传递歌单数据
state.js中:添加歌单对象
disc: {}
mutation-type.js中:定义type常量
export const SET_DISC = ‘SET_DISC’
mutation.js中:创建更改函数
[types.SET_DISC](state, disc){
state.disc = disc
}
getters.js中:定义数据映射
export const disc = state => state.disc
recommend.vue中:使用mapMutations修改disc
import {mapMutations} from ‘vuex’

…mapMutations({
setDisc: ‘SET_DISC’
})

selectItem(item) {
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …h: `/recommend/{item.dissid}`
})
this.setDisc(item) //更改state中的disc
}
disc.vue中:通过mapGetters获取到date中的disc
import {mapGetters} from 'vuex

computed: {
…mapGetters([
‘disc’
])
}
传递数据:获取数据在computed里面,设置数据在methods里面
歌单详情页数据抓取

api->recommend.js中:添加getSonglist接口
export function getSongList (disstid) {
const url = ‘/api/getSongList’

 const data = Object.assign({}, commonParams, {
     uin: 0,
     format: 'json',
     notice: 0,
     needNewCode: 1,
     new_format: 1,
     pic: 500,
     disstid, //关键数据
     type: 1,
     json: 1,
     utf8: 1,
     onlysong: 0,
     picmid: 1,
     nosign: 1,
     song_begin: 0,
     platform: 'h5',
     song_num: 100,
     _: +new Date()
})

return axios.get(url, {
     params: data
}).then((res) => {
     return Promise.resolve(res.data)
})

}
因为数据也经过加密,在webpack.dev.config.js中模仿header:
app.get(’/api/getSongList’, function (req, res) {
var url = ‘https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg’
axios.get(url, {
headers: {
referer: ‘https://y.qq.com/’,
host: ‘c.y.qq.com’
},
params: req.query
}).then((response) => {
res.json(response.data)
}).catch((e) => {
console.log(e)
})
})
注意:后端配置之后,一定要重新启动!!!

   歌单详情页数据的处理和应用

调用getSongList()方法获取数据,在created()时获取
import {getSongList} from ‘@/api/recommend’

_getSongList () {
if(!this.disc.dissid){ //在歌单详情页强制刷新后,即没有获得id时,回退到推荐页面
this.$router.push(’/recommend’)
return
}
getSongList(this.disc.dissid).then((res) => {
if (res.code === ERR_OK) {
this.songs = this._normalizeSongs((res.cdlist[0].songlist))
// console.log(res)
// console.log(res.cdlist[0].songlist)
// console.log(this._normalizeSongs(res.cdlist[0].songlist))
}
})
}
获得数据后,在methods中对数据进行一些处理
同歌手详情页,歌曲的播放url中的vkey需要发送请求获取,同时将处理好的数据封装新的Song实例
import {ERR_OK} from ‘@/api/config’
import {creatSongList} from ‘@/common/js/song’
import {getMusic} from ‘@/api/singer’

_normalizeSongs (list) {
let ret = []
list.forEach((musicData) => {
if (musicData.id && musicData.album) {
// ret.push(creatSongList(musicData))
getMusic(musicData.mid).then((res) => {
// console.log(res)
if(res.code === ERR_OK){
// console.log(res.data)
const svkey = res.data.items
const songVkey = svkey[0].vkey
const newSong = creatSongList(musicData, songVkey)
ret.push(newSong)
}
})
}
})
return ret
}
其中:调用getMusic()获取播放地址的vkey,调用creatSongList()实例化Song对象

common->js->song.js中: 创建creatSongList()
export function creatSongList (musicData, songVkey) {
return new Song({
id: musicData.id,
mid: musicData.mid,
singer: filterSinger(musicData.singer),
name: musicData.name,
album: musicData.albumname,
duration: musicData.interval,
image: https://y.gtimg.cn/music/photo_new/T002R300x300M000${musicData.album.mid}.jpg?max_age=2592000,
//注意guid以实时数据为主
url: http://ws.stream.qqmusic.qq.com/C400${musicData.mid}.m4a?vkey=${songVkey}&guid=6319873028&uin=0&fromtag=66
})
}
二、排行榜及详情页开发
排行榜数据抓取

在api目录下:创建rank.js添加获取数据的接口
import jsonp from ‘@/common/js/jsonp’
import {commonParams, options} from ‘./config’

export function getTopList() {
const url = “https://c.y.qq.com/v8/fcg-bin/fcg_myqq_toplist.fcg”

 const data = Object.assign({}, commonParams, {
          platform: 'h5',
          needNewcode: 1
 })

 return jsonp(url, data, options)

}
rank.vue中:调用getTopList()方法获取数据,在created()时获取
import {getTopList} from ‘@/api/rank’
import {ERR_OK} from ‘@/api/config’

created() {
this._getTopList()
},
methods: {
_getTopList() {
getTopList().then((res) => {
if(res.code === ERR_OK){
console.log(res.data.topList)
}
})
}
}
排行榜数据应用

在data中维护数据
topList: []
获取数据后赋值
this.topList = res.data.topList
将数据填入DOM:应用scroll组件替换父元素

并传入topList数据实现滚动

优化:应用loading组件,设置当topList没有内容时显示loading
优化:应用mixin,实现播放器底部适配
榜单详情页布局及Vuex实现路由数据通讯

路由的跳转
router->index.js中:设置Rank的二级路由
import TopList from ‘@/components/top-list/top-list’

{
path: ‘/rank’,
component: Rank,
children: [
{
path: ‘:id’,
component: TopList
}
]
}
rank.vue中:添加路由容器,给列表添加点击事件,触发路由的跳转


@click=“selectItem(item)”
selectItem(item) {
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: … path: `/rank/{item.id}`
})
}
Vuex传递数据
state.js中:定义数据
topList: {}
mutation-types.js中:定义type常量
export const SET_TOP_LIST = ‘SET_TOP_LIST’
mutations.js中:添加修改topList的方法
[types.SET_TOP_LIST](state, topList){
state.topList = topList
}
getters.js中:添加topList的数据映射
export const topList = state => state.topList
写入和获取state数据
rank.vue中:通过mapMutations写入数据
import {mapMutations} from ‘vuex’

this.setTopList(item)

…mapMutations({
setTopList: ‘SET_TOP_LIST’
})
top-list.vue中:通过mapGatters拿到数据
import {mapGetters} from ‘vuex’

computed: {
…mapGetters([
‘topList’
])
}
剩下的就是获取数据用computed,设置数据用methods

   榜单详情歌曲数据的抓取

需求:榜单本身的背景图不好看,想要抓取榜单详情歌曲的图片作为背景图
问题:原请求是Ajax请求,不能跨域,但也支持jsonp请求,只是没有格式化不方便查看数据
解决: 在线网站www.bejson.com 中格式化为json文件
因为这块数据QQ音乐也做了加密,这里抓取数据同歌单详情页方式
api->rank.js中:添加获取数据的接口
export function getMusicList(topid) {
const url = “https://c.y.qq.com/v8/fcg-bin/fcg_v8_toplist_cp.fcg”

 const data = Object.assign({}, commonParams, {
          page: 'detail',
          type: 'top',
          tpl: 3,
          platform: 'h5',
          needNewcode: 1
 })

 return jsonp(url, data, options)

}
top-list.vue中:调用getMusicList()方法获取数据,在created()时获取
import {getMusicList} from ‘@/api/rank’
import {ERR_OK} from ‘@/api/config’

created() {
this._getMusicList()
}

getMusicList(this.topList.id).then((res) => {
if(res.code === ERR_OK){
this.songs = this._normalizeSongs(res.songlist)
// console.log(res.songlist)
}
})
获得数据后,在methods中对数据进行一些处理:同歌单详情页,歌曲的播放url中的vkey需要发送请求获取,同时将处理好的数据封装新的Song实例
import {getMusic} from ‘@/api/singer’
import {createSong} from ‘@/common/js/song’

_normalizeSongs(list) {
let ret = []
list.forEach((item) => {
const musicData = item.data
// console.log(musicData)
if (musicData.songid && musicData.albumid) {
getMusic(musicData.songmid).then((res) => {
// console.log(res)
if(res.code === ERR_OK){
// console.log(res.data)
const svkey = res.data.items
const songVkey = svkey[0].vkey
const newSong = createSong(musicData, songVkey)
ret.push(newSong)
}
})
}
})
return ret
}
这样数据就获取到了,剩下的把songs的数据传递给子组件就可以了

把bgImage的图片换成榜单第一首歌的图片
bgImage() {
if (this.songs.length) {
return this.songs[0].image
}
return this.topList.picUrl
}
带排行的song-list组件的扩展和应用

添加rank的DOM结构、图片以及样式
添加props字段rank,默认false,设置只有当rank为true时排行显示
rank: {
type: Boolean,
default: false
}

定义两个方法分别获得动态绑定的class和文案 {{getRankText(index)}} getRankCls(index) { if(index<=2) { return `icon icon${index}` }else{ return 'text' } }, getRankText(index) { if(index > 2) { return index + 1 } } music-list.vue作为中间组件,也需要扩展一个props字段rank rank: { type: Boolean, default: false } 传入 这样就把最外层父组件传入的rank应用到了song-list.vue组件中 top-list.vue中维护数据rank为true,同时传入中
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值