VUE移动端音乐APP学习【十七】:歌单详情页组件开发
歌单详情页基础开发
歌单详情页和歌曲列表页面是非常类似的,只是数据上的不同。以下是这个组件的基本结构:可以看到和我们的singer-detail一样都有transition动画以及使用了music-list组件,接下来就是想办法把music-list数据传进去。
<template> <transition> <music-list></music-list> </transition> </template> <script> import MusicList from '../music-list/music-list'; export default { name: 'disc', components: { MusicList, }, }; </script> <style lang="scss" scoped> .slide-enter-active, .slide-leave-active { transition: all 0.3s; } .slide-enter, .slide-leave-to { transform: translate3d(100%, 0, 0); } </style>
这个组件首先是个二级路由,需要先去router下设置成二级路由。
{ path: '/recommend', name: 'Recommend', component: Recommend, children: [{ path: ':id', component: Disc, }], }
然后回到recommend添加<router-view>,并且给歌单列表添加点击事件,就可以实现路由跳转
<div class="recommend" ref="recommend"> <scroll> .... <li @click="selectItem(item)" v-for="item in discList" class="item" :key="item.id"> .... </scroll> <router-view></router-view> </div>
selectItem(item) { this.$router.push({ path: `/recommend/${item.dissid}`, }); },
通过vuex把歌单数据传过去,首先在state下面定义歌单的对象,其次添加mutation-types,利用它在mutations添加更改函数
//state.js const state = { singer: {}, // 播放状态默认为暂停 playing: false, // 播放器默认为收起 fullScreen: false, // 播放列表 playlist: [], // 顺序列表 sequenceList: [], // 播放模式默认为顺序播放 mode: playMode.sequence, // 当前播放索引 currentIndex: -1, // 歌单对象 disc: {}, }; //mutation-types.js export const SET_DISC = 'SET_DISC'; //mutations.js [types.SET_DISC](state, disc) { state.disc = disc; },
最后设置它的getters方法
export const disc = (state) => state.disc;
通过mustation去设置disc,有了mutation之后就可以在刚才的点击方法里调用更改state里的disc
//recommend.vue import { mapMutations } from 'vuex'; ...mapMutations({ setDisc: 'SET_DISC', }), selectItem(item) { this.$router.push({ path: `/recommend/${item.id}`, }); this.setDisc(item); },
在disc.vue就可以接收使用这个数据
<template> <transition> <music-list :title="title" :bg-image="bgImage"></music-list> </transition> </template> import { mapGetters } from 'vuex'; computed: { title() { return this.disc.name; }, bgImage() { return this.disc.picUrl; }, ...mapGetters([ 'disc', ]), },
抓取歌单详情数据
在recommend.js下设置接口
export function getSongList(id) { return axios.get(`api/playlist/detail?id=${id}`); }
在disc.vue调用api发起请求,获取数据
import { ERR_OK } from '../../api/config'; created() { this._getSongList(); }, methods: { _getSongList() { getSongList(this.disc.id).then((res) => { if (res.code === ERR_OK) { console.log(res.playlist.tracks); } }); }, },
歌单详情数据应用
通过createSong方法处理歌单数据将歌曲传入music-list,同时可以看到组件复用的效果
<template> <transition> <music-list :title="title" :bg-image="bgImage" :songs="songs"></music-list> </transition> </template> import { createSong } from '../../common/js/song'; data() { return { songs: [], }; }, _normalizeSongs(list) { let ret = []; list.forEach((musicData) => { if (musicData.id && musicData.al.id) { ret.push(createSong(musicData)); } }); console.log(ret); return ret; }, },
最后需要处理个小问题,当刷新页面的时候,数据就丢失了,解决方法和歌手详情页的逻辑一样,在_getSongList方法添加判断如果获取不到歌单id就回退上一个路由推荐页面
_getSongList() { if (!this.disc.id) { this.$router.push('/recommend'); return; } getSongList(this.disc.id).then((res) => { if (res.code === ERR_OK) { console.log(res.playlist.tracks); this.songs = this._normalizeSongs(res.playlist.tracks); } }); },