一個(gè)基于Vue全家桶(Vue,Vue-router,Vuex)開發(fā)的單頁面音樂應(yīng)用,在學(xué)習(xí)H5和JavaScript的最開始的時(shí)候就想做一個(gè)音樂播放器,現(xiàn)在終于實(shí)現(xiàn)了當(dāng)初的想法。雖然這個(gè)播放器目前的功能還較為簡單,可能存在一些兼容性問題,但是我有時(shí)間的話會(huì)繼續(xù)完善這個(gè)項(xiàng)目。歡迎喜歡的朋友star、follow??,十分感謝
在這里主要是記錄一下自己開發(fā)過程中遇到的坑和新學(xué)習(xí)到的東西,相對(duì)于這次的實(shí)踐做一個(gè)總結(jié)。
因?yàn)轫?xiàng)目是放在自己的騰訊云服務(wù)器上的,所以有可能打開速度比較慢,請(qǐng)見諒。
感謝由 https://github.com/Binaryify/NeteaseCloudMusicApi 所提供的Node.js版網(wǎng)易云音樂API
項(xiàng)目預(yù)覽








1.關(guān)于技術(shù)棧的選擇
這個(gè)項(xiàng)目的依賴模塊
<pre>
"dependencies": {
"axios": "^0.16.2",
"material-design-icons": "^3.0.1",
"muse-ui": "^2.1.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue": "^2.3.3",
"vue-awesome-swiper": "^2.5.4",
"vue-router": "^2.3.1",
"vuex": "^2.3.1"
}</pre>
Vue + Vue-router + Vuex(Vue全家桶)
axios(網(wǎng)絡(luò)請(qǐng)求)
muse-ui(一個(gè)Vue的material design 組件庫)
stylus(css預(yù)處理器)
后端是采用了由 https://github.com/Binaryify/NeteaseCloudMusicApi 所提供的Node.js版網(wǎng)易云音樂API,可以非常方便的獲取到數(shù)據(jù)
2.應(yīng)用分析
因?yàn)槭情_發(fā)一個(gè)網(wǎng)絡(luò)播放器,所以基本的流程是:首頁 => 歌單|專輯|排行榜(未完成)|搜索 => 歌曲播放 => 播放界面以及播放列表?;谶@樣的流程,我將整個(gè)應(yīng)用拆分成了幾個(gè)小模塊:首頁、排行榜、搜索、歌單、專輯、搜索列表、正在播放。這樣讓整個(gè)應(yīng)用的邏輯更加清晰,在后期需要調(diào)整或者查錯(cuò)的時(shí)候也更加方便一些。
3.關(guān)于正在播放部分
先看一下效果圖

可以看到,正在播放這一組件實(shí)際上是由底部的工具欄、播放列表和彈出的專輯頁面組成。實(shí)際上目前這個(gè)組件的邏輯非常簡單:把目前的播放列表和當(dāng)前播放的索引儲(chǔ)存在stroe里面,然后再創(chuàng)建這個(gè)組件時(shí)獲取信息。每次播放歌曲時(shí)將提取出來的需要的信息儲(chǔ)存在store里面,而musicTray(正在播放組件)中所綁定的相關(guān)信息也會(huì)實(shí)時(shí)更新。在每次播放新歌曲時(shí)創(chuàng)建一個(gè)新的audio對(duì)象,然后將舊的audio對(duì)象刪除,之后再將新創(chuàng)建的audio對(duì)象儲(chǔ)存在store里面,這樣可以保證在切換頁面時(shí)播放不會(huì)中斷。
4.關(guān)于搜索
在搜索頁面發(fā)起搜索請(qǐng)求后將用戶填寫的搜索信息儲(chǔ)存至store中,然后在搜索列表頁面每次creat的同時(shí)獲取該信息并發(fā)起請(qǐng)求。在每次創(chuàng)建時(shí)請(qǐng)求的只包括歌曲列表,專輯、歌單、歌手(未完成)等在每次點(diǎn)擊頂部tab時(shí)再根據(jù)用戶的需求獲取相關(guān)數(shù)據(jù),這樣可以減少單次數(shù)據(jù)量,提高用戶的試用體驗(yàn)。具體的代碼為:
<pre>
handleTabChange(val) {
this.activeTab = val
if (val === 'songLists') {
if (this.songLists.length === 0) {
this.$store.commit('isLoading')
this.$http.get(api.search(this._searchName, val, this.offset)).then(response => {
this.songLists = response.data.result.playlists
this.$store.commit('isLoading')
})
}
}
}
</pre>
5.關(guān)于加載時(shí)的動(dòng)畫
我采用的方案是創(chuàng)建了一個(gè)loading組件,然后將他的容器的寬高定為屏幕的大小,容器中播放css3動(dòng)畫,用一個(gè)變量控制loading組件的顯示(v-if="isLoading"),將這個(gè)變量存儲(chǔ)在store中,以確保每次改變后在不同的組件中都能夠獲取到正確的變量。將loading組件在APP.vue中引入,之后再通關(guān)控制store中的isLoading變量去控制loading組件的顯示。
6.關(guān)于項(xiàng)目的搭建(node.js服務(wù)端的布置)
因?yàn)檫@個(gè)應(yīng)用需要自己使用node搭建服務(wù)端,所以沒辦法使用GitHub pages,正好自己有一個(gè)騰訊云學(xué)生服務(wù)器,所以想把服務(wù)端布置在騰訊云的服務(wù)器上。但是自己的博客又布置在這個(gè)服務(wù)器上,服務(wù)器是使用apache作為服務(wù)端,剛開始直接在服務(wù)器上安裝node.js然后將應(yīng)用上傳至服務(wù)器,發(fā)現(xiàn)無法運(yùn)行。經(jīng)過搜索之后發(fā)現(xiàn)要在 Apache 的配置文件中,打開 mod_proxy 和 mod_proxy_http模塊并將node升級(jí)至最新穩(wěn)定版,才能夠正常運(yùn)行node.js應(yīng)用。