輕量級音樂播放器搭建 6

輕量級音樂播放器搭建 6

 

如今把在music-controller組件中觀察的state狀態轉移到music-player之中:vue

  music-player.vue
<script>
 ......
 import {mapState} from 'vuex'
 export default {
......
   computed: {
     ...mapState([
       'likeThisMusic',
       'playMode',
       'privateSongList'
    ])
  },
   methods: {
     ......
     togglePlaying (isPlaying) {
       console.log(isPlaying)
       if (isPlaying === true) {
         this.$refs.audio.play()
      } else {
         this.$refs.audio.pause()
      }
    },
     _handlePlayModeChanged () {
       console.log('PLAY MODE CHANGED!')
       console.log(this.$store.state.playMode)
    },
     _handleLikeThisMusicChanged () {
       console.log('LIKE THIS MUSIC CHANGED')
       console.log(this.$store.state.likeThisMusic)
    },
  },
   watch: {
     playMode () {
       this._handlePlayModeChanged()
    },
     likeThisMusic () {
       this._handleLikeThisMusicChanged()
    }
  }
}
</script>

若是播放狀態改變了,那麼要怎麼修改才能實現對下一首歌的播放進行控制?在不大修改以前的代碼的狀況下,能夠對當前的一個data變量作更改。由於一首歌結束以後,就是調用的_playDefaultMusic(currentMusicIndex)方法,那播放模式的改變其實就是對接下來的播放歌曲進行選擇,那麼就對currentMusicIndex作更改。可是這樣有個問題是隻能對接下來的那一首歌進行更改,而播放模式是一個長期的持續的狀態。那可不能夠有一個當前播放列表,每次切換格式的時候就對列表進行更新。好比說大前提是用戶有私有的(播放模式只在播放私有列表有效,推薦FM中的播放模式無心義)若干播放列表。播放某個列表就是從某個狀態切換成單曲循環,那麼就是把當前的播放歌曲替換成當前的播放列表。vuex

算了,太麻煩。我感受仍是要修改原來的代碼。就是將_playDefaultMusic(currentMusicIndex)方法進行修改,在方法中經過三種不一樣的狀態來調整下一個currentMusicIndex。因此更新函數以下:promise

  
_playDefaultMusic () {
 // 0表明單曲循環,1表明順序播放,2表明隨機播放
 if (this.$store.state.playMode === 2) {
   // 生成隨機索引
   this.currentMusicIndex = Math.floor(Math.random() * this.defaultMusicList.length)
} else if (this.$store.state.playMode === 1) {
   if (this.currentMusicIndex === this.defaultMusicList.length - 1) {
     this.currentMusicIndex = 0
  } else {
     this.currentMusicIndex = this.currentMusicIndex + 1
  }
   ......
}
}

如今這個切換播放模式的功能就作完了,沒有報錯,可是如今還不可以驗證是否能夠正常使用。由於到如今爲止尚未用戶的概念,更別說登錄與用戶的私人播放列表了。因此這個部分的測試須要以後再進行測試。dom

接下來是喜歡這首歌的功能,一樣的這個功能也不能如今進行測試,因此如今先作可以完成的這一部分。函數

  
if (this.$store.state.likeThisMusic === true) {
 let thisMusic = Object.assign({},this.defaultMusicList[this.currentMusicIndex])
 // 將thisMusic對象push進用戶的喜歡的歌曲的列表
} else {
 // 取消喜歡一首歌相對較爲複雜,應當以歌曲id做爲標記。
 // 再用戶喜歡的歌曲的列表中找到對應id歌曲並進行刪除
}

既然這個也還不能寫,就進行下一個控制——上一首歌/下一首歌。下一首歌比較簡單,首先作這個,由於是music-controller接受的控制,因此先回到這個組件的代碼:測試

  
changeToNextMusic () {
 console.log('changToNextMusic')
 this.$emit('changeToNextMusic')
},

很簡單,就是子組件在觸發點擊事件的時候執行此函數,而後這個函數觸發一個自定義的changeToNextMusic事件來與父組件進行通訊。如今回到父組件:this

  
changeToNextMusic () {
 this._playDefaultMusic()
},

父組件監聽changeToNextMusic事件,並執行changeToNextMusic函數,這個函數執行私有函數_playDefaultMusic,就能夠完成切換到下一首歌的操做。這個很簡單,而後是播放上一首歌,這個就比以前的下一首歌功能要複雜。由於須要有一個容器來儲存以前播放的歌,可是有個問題就是當用戶登錄與不登陸的時候這個功能就不同了。由於用戶若是登錄以後,會有本身的播放記錄。可是若是沒有登錄,那麼播放記錄就是本地的播放記錄。這還好,可是若是用戶登錄以後又再下線,就要求必須有本地與用戶兩個播放記錄。用戶在線的話就把當前的歌曲添加到本地已播放歌曲與用戶已播放記錄,不在線的話就只將當前的歌曲添加到本地的已播放記錄。這樣的話就是如今先不用管用戶的播放記錄,現階段只考慮本地播放記錄。atom

因此就要實現一個播放記錄,顯然使用棧來儲存比較好,因爲這是一個h5應用,因此我以爲播放記錄儲存30條足夠了。可是現階段30條很差調試,因此我先將棧的容量設爲5條。修改一個地方,以前的defaultMusicList改名爲currentMusicList,這是由於如今的播放不是隻針對那一個推薦的歌單,而是全部的歌曲列表,咱們請求的是一個defaultMusicList,能夠將這個列表賦給currentMusicList。播放記錄我放到music-player組件中,實現以下:spa

  data () {
 return {
......
   history: [],
}
},

_playDefaultMusic () {
 ......
 // 更新本地歷史紀錄
 if (this.history.length === this.historyLength) {
   for (let i = 1; i < this.historyLength; i++) {
     this.history[i - 1] = this.history[i]
  }
   this.history[this.historyLength - 1] = this.currentMusicList[this.currentMusicIndex]
} else {
   this.history.push(this.currentMusicList[this.currentMusicIndex])
}
 // 更新用戶歷史紀錄
},

如今這樣就是用戶每自動切換到下一首歌或者是手動切歌到下一首歌,都會將這首新的歌添加到播放記錄中。至於用戶手動點擊選擇歌曲來播放歌曲的狀況就到以後再考慮。而後我向控制播放記錄的長度,那麼當不斷push進播放記錄到了長度爲6的時候,就將以前的元素去除。用shift、slice(1)等各類方法都不行,嚴格模式下不能使用這些函數,因此採用遍歷,衰。調試

另外發現了兩個問題,就是有時報錯:

  
Uncaught (in promise) DOMException: The play() request was interrupted by a new load request. https://goo.gl/LdLk22

還有就是隨機播放與播放記錄這兩個地方都有可能出現相同的歌曲,應當對有重複的狀況進行處理。明天作,回宿舍了。

 

挖坑待填:

  1. 用戶喜歡歌曲的添加與刪除

  2. 用戶播放記錄的實現

  3. 更新用戶播放記錄。

參考連接:

  1. js 生成僞隨機數

  2. js 生成真正的隨機數

  3. assign 對象拷貝

相關文章
相關標籤/搜索