【音樂App】—— Vue-music 項目學習筆記:歌單及排行榜開發


前言:以下內容均為學習慕課網高級實戰課程的實踐爬坑筆記。

項目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中:
  1. 添加路由容器
    <router-view></router-view>
  2. 給歌單列表添加點擊事件
    @click="selectItem(item)"
  3. 定義selectItem()實現路由跳轉
    selectItem(item) { this.$router.push({ path: `/recommend/${item.dissid}` }) }
  • 使用vuex傳遞歌單數據
  1. state.js中:添加歌單對象
    disc: {}
  2. mutation-type.js中:定義type常量
    export const SET_DISC = 'SET_DISC'
  3. mutation.js中:創建更改函數
    [types.SET_DISC](state, disc){ state.disc = disc }
  4. getters.js中:定義數據映射
    export const disc = state => state.disc
  • recommend.vue中:使用mapMutations修改disc
    import {mapMutations} from 'vuex' ...mapMutations({ setDisc: 'SET_DISC' }) selectItem(item) { this.$router.push({ path: `/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中對數據進行一些處理
  1. 同歌手詳情頁,歌曲的播放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對象

  2. 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組件替換父元素<div>並傳入topList數據實現滾動
    <scroll class="top-list" :data="topList">
  • 優化:應用loading組件,設置當topList沒有內容時顯示loading
  • 優化:應用mixin,實現播放器底部適配

       榜單詳情頁布局及Vuex實現路由數據通訊

  • 路由的跳轉
  1. router->index.js中:設置Rank的二級路由
    import TopList from '@/components/top-list/top-list' { path: '/rank', component: Rank, children: [ { path: ':id', component: TopList } ] }
  2. rank.vue中:添加路由容器,給列表添加點擊事件,觸發路由的跳轉

    <router-view></router-view> @click="selectItem(item)"
    selectItem(item) { this.$router.push({ path: `/rank/${item.id}` }) }
  • Vuex傳遞數據
  1. state.js中:定義數據
    topList: {}
  2. mutation-types.js中:定義type常量
    export const SET_TOP_LIST = 'SET_TOP_LIST'
  3. mutations.js中:添加修改topList的方法
    [types.SET_TOP_LIST](state, topList){ state.topList = topList }
  4. getters.js中:添加topList的數據映射
    export const topList = state => state.topList
  • 寫入和獲取state數據
  1. rank.vue中:通過mapMutations寫入數據
    import {mapMutations} from 'vuex'
    
    this.setTopList(item) ...mapMutations({ setTopList: 'SET_TOP_LIST' })
  2. top-list.vue中:通過mapGatters拿到數據
    import {mapGetters} from 'vuex' computed: { ...mapGetters([ 'topList' ]) }

    剩下的就是獲取數據用computed,設置數據用methods

       榜單詳情歌曲數據的抓取

  • 需求:榜單本身的背景圖不好看,想要抓取榜單詳情歌曲的圖片作為背景圖
  • 問題:原請求是Ajax請求,不能跨域,但也支持jsonp請求,只是沒有格式化不方便查看數據
  • 解決: 在線網站www.bejson.com 格式化為json文件
  • 因為這塊數據QQ音樂也做了加密,這里抓取數據同歌單詳情頁方式
  1. 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) }
  2. 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)
     } })
  3. 獲得數據后,在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 }
    <div class="rank" v-show="rank">
  • 定義兩個方法分別獲得動態綁定的class和文案
    <span :class="getRankCls(index)">{{getRankText(index)}}</span>
    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 }
  1. 傳入<song-list>
    <song-list :rank="rank"></song-list>
  2. 這樣就把最外層父組件傳入的rank應用到了song-list.vue組件中
  3. top-list.vue中維護數據rank為true,同時傳入<music-list>中

 注:項目來自慕課網


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM