基於 Vue + vuex + vue-router + vue-axios +better-scroll + Stylus + px2rem 等開發的移動端音樂App,UI 界面是看着本身手機的網易雲音樂寫的、flex 佈局適配常見移動端。html
也許是服務器緣由有時進入頁面首頁,左右滑動切換頁面效果沒有用。這時請從新刷
新頁面,有時頁面加載的有點慢,請耐心等待。
複製代碼
寫這個呢是由於最近學了Vue,想鞏固下本身所學的知識。我的認爲寫項目能夠更好的發現本身的不足。寫音樂呢是由於網易有開源的接口,還有本身喜歡聽歌!vue
炎炎夏日,你在家裏吹着空調吃着冰鎮西瓜沒準還躺在沙發上看着本身喜歡的電影。而我卻在學校看着電腦敲着代碼沒準還正抓着頭皮改着不知道哪裏出錯了的bug。來自大三在校生的感慨,因此大佬請輕噴!!但個人問題請大佬務必告知,或者有更好的解決方案也同樣,畢竟誰不想學到更多的知識呢?react
沒有切圖就是看着手機本身寫的,因此樣式有點難看。ios
記錄本身的學習,由於有些東西你不用它遺忘的是很快的。但願之後想撿起來的時候看看本身的筆記能有所幫助。就算沒啥幫助,等多年之後回頭看看本身曾經寫的代碼,也挺有意思的!git
Vue: 用於構建用戶界面的 MVVM 框架github
Vue-router: 單頁面應用提供的路由管理vue-router
vuex:Vue集中狀態管理,大型項目所必需的數據存儲,讓多個組件相互交互、共享狀態時很是便捷vuex
better-scroll:解決移動端各類滾動場景需求的插件,使移動端滑動體驗更加流暢axios
stylus: 一種Css預編譯處理器api
px2rem: 移動端自適應的一種方法
Vue-axios: 用於請求API接口
NeteaseCloudMusicApi:網易雲音樂 NodeJS 版 API,提供音樂數據
iconfont :阿里巴巴圖標庫,十分強大的一個圖標庫
axios方法封裝
axios.defaults.timeout = 10000
axios.defaults.baseURL = 'http://localhost:3000'
// 返回狀態判斷
axios.interceptors.response.use((res) => {
if (res.data.code !== 200) {
console.log('網絡異常')
vue.$toast('網絡異常')
vue.$hideLoading()
return Promise.reject(res)
}
return res
}, (error) => {
console.log('網絡異常')
vue.$toast('網絡異常')
vue.$hideLoading()
return Promise.reject(error)
})
export function fetchGet(url, param) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: param
})
.then(response => {
resolve(response.data)
}, err => {
reject(err)
})
.catch((error) => {
reject(error)
})
})
}
複製代碼
axios接口請求(只展現幾條避免太冗長)
export default {
//歌單
DiscLists(params) {
return fetchGet('/top/playlist', params)
},
// 歌單詳情
SongList(params) {
return fetchGet('/playlist/detail', params)
},
//歌曲搜索
MusicSearch(params){
return fetchGet('/search',params)
},
//獲取歌曲的url
MusicUrl (id){
return fetchGet('/top/playlist',{
id
})
},
//根據id獲取mv數據
getMVDetail(params){
return fetchGet('/mv/detail', params)
},
//手機號登陸
phoneLogin(params){
return fetchGet('/login/cellphone', params)
},
//登陸後根據用戶id獲取用戶歌單
getUserSonglist(params){
return fetchGet('/user/playlist', params)
},
}
複製代碼
routes: [
主頁面
{path: '/', component: Main},
{
//歌單詳情頁
path: '/songdetail',
name:songdetail,
component: songdetail
},
//歌單廣場
{
path: '/songSquare/songSquare',
name:songSquare,
component: songSquare
},
//搜索頁
{
path: '/search',
name:search,
component: search
},
//搜索詳情頁
{
path: '/searchDetail',
name:searchDetail,
component: searchDetail
},]
複製代碼
modules(只展現music)
import * as types from '../types'
const state = {
songlist : [],
songs : '可樂',
searchHistory : ['薛之謙']
}
const mutations = {
// 上拉刷新歌單
[types.RESH_SONG_LIST](state, songlist) {
state.songlist = songlist;
// console.log(state.songlist)
},
//保存搜索歷史
[types.SAVE_SEARCH_HISTORY](state, searchHistory) {
//數組去重,避免用戶搜索相同關鍵字屢次而加入相同的關鍵字
if(!state.searchHistory.includes(searchHistory)){
state.searchHistory.unshift(searchHistory)
}
// console.log(state.searchHistory)
},
//刪除搜索歷史 DELETE_SEARCH_HISTORY
[types.DELETE_SEARCH_HISTORY](state) {
state.searchHistory = []
},
}
const actions = {
// 上拉刷新歌單
reshSongList ({commit, state}, songlist) {
console.log(songlist);
// let playHistory = state.playHistory.slice()
// playHistory = [...playHistory, song]
commit(types.RESH_SONG_LIST, songlist)
},
//保存搜索歷史
saveSearchHistory({commit, state}, searchHistory) {
console.log(searchHistory);
commit(types.SAVE_SEARCH_HISTORY, searchHistory)
},
//刪除搜索歷史 DELETE_SEARCH_HISTORY
deleteSearchHistory({commit, state}) {
commit(types.DELETE_SEARCH_HISTORY)
},
}
const getters = {
songlist: state => state.songlist,
songs : state => state.songs,
searchHistory : state => state.searchHistory,
}
export default {
state,
mutations,
actions,
getters
}
複製代碼
types(剛開始還記得常量應該大寫,寫着寫着就忘了!尷尬)
export const RESH_SONG_LIST = 'RESH_SONG_LIST' // 刷新歌單
export const SAVE_SEARCH_HISTORY = 'SAVE_SEARCH_HISTORY'//保存搜索歷史
export const DELETE_SEARCH_HISTORY = 'DELETE_SEARCH_HISTORY'//刪除搜索歷史
export const yuncun_video = 'yuncun_video'//獲取雲村精選視頻
export const inland_video = 'inland_video'//獲取內地視頻
export const hongkong_video = 'hongkong_video'//獲取港臺視頻
export const occident_video = 'occident_video'//獲取歐美視頻
export const japan_video = 'japan_video'//獲取日本視頻
export const update_login = 'update_login'//修改登陸狀態
export const save_userId = 'save_userId'//保存用戶id
export const save_profile = 'save_profile'//保存用戶信息
export const save_songlist = 'save_songlist'//保存用戶歌單
export const save_userDetail = 'save_userDetail'//保存用戶詳情
複製代碼
store.js(將模塊導出)
import Vue from 'vue'
import Vuex from 'vuex'
// import com from './modules/com'
import music from './modules/music'
import video from './modules/video'
import myLogin from './modules/myLogin'
Vue.use(Vuex)
export default new Vuex.Store({
modules : {
music,
video,
myLogin,
}
})
複製代碼
推薦頁面、歌單詳情、歌單廣場頁面、排行榜詳情、搜索頁面、歌手列表、播放列表、我的中心等功能。
頁面切換
上拉刷新
api.Recommend(params).then(res =>{
if(res.code === 200){
this.songlist = [];
let length = res.playlists.length
while(this.songlist.length<6){
var random = Math.floor(Math.random()*(length-6+1)+1);
//數組去重
if (!this.songlist.includes(res.playlists[random])) {
this.songlist.push(res.playlists[random]);
}
}
this.$store.dispatch("reshSongList",this.songlist)
}
})
複製代碼
這個頁面的父子組件的傳值方式用了好幾種方法
想了解更多方法請點這裏
以前學習的時候覺得只有一種,但當時感受用第一種這種方法有點麻煩,就去百度了一下,發現還有好多方法。因此寫項目仍是能夠學到更多知識的
這個頁面應該最複雜的一個頁面了,當時沒考慮的好,知道頁面要複用,但仍是沒有設計的很好,致使有幾個頁面仍是複製代碼改了傳入的數據。若是當時數據所有是由父組件傳過來的話,設計的好一點,一個詳情頁就能夠了。
下面是這個頁面的部分方法,比較多我就用圖片形式展現了
歌單詳情頁中用了個組件,也就是底部播放
watch:{
index (val){
const params = {
id: this.songs[val].id
};immediate: true;
this.play();
api.SongUrl(params).then( (res)=>{
this.songdata = res.data;
this.$refs.audio.src = this.songdata[0].url;
this.songAvtart = this.songs[val].al.picUrl;
this.songname = this.songs[val].name;
this.singer = this.songs[val].ar[0].name;
console.log(res.data)
}).then(()=>{
// this.$refs.audio.play();
this.play();
this.$emit('play');
// this.con = false;
})
},
},
複製代碼
用watch監聽,父組件傳過來的index值,從而點擊哪首歌播放哪首歌
下面是底部播放器中的方法
methods:{
//歌曲播放完自動播放下一首
ended(){
//子組件調用父組件的方法
console.log('father');
this.$parent.next();
},
//播放音樂
play () {
console.log(this.$refs.audio)
this.$refs.audio.play();
this.con = false;
//圖片旋轉
this.rotate = true;
//告訴父組件正在播放
this.$emit('play');
},
//暫停音樂
pause(){
this.con = true;
this.$refs.audio.pause();
//中止旋轉
this.rotate = false;
//告訴父組件暫停播放
this.$emit('pause');
},
//全屏播放
fullPlay(){
this.$emit('fullPlay');
}
},
複製代碼
1.能夠在輸入框中輸入你想搜索的歌曲 2.也能夠點擊搜索歷史搜索 3.點擊熱搜榜也能夠搜索
只有個上拉加載功能
第一次去到個人頁面,若是沒登陸的話,須要先登陸。登陸完以後用戶id會保存在 Vuex中。
也沒啥好說的,點擊視頻播放就完事了。每次只能播放一個視頻
十分感謝蝸牛老師教的Vue課程,蝸牛老師講課是真的透徹!
最後送本身一句話:你抓頭改bug的樣子雖然有些狼狽,但你努力寫代碼的樣子真的很帥!!共勉。