VUE移動端音樂APP學習【二十七】:player核心的修改優化
阿新 • • 發佈:2021-07-14
One.
缺陷:當開啟播放器快速切換歌曲時,按下暫停播放,發現歌詞和背景音樂都仍在播放,這顯示是不符合預期的。
原因:程式碼watch currentSong的變化以後做清理操作,然後執行audio.play()和獲取歌曲。這裡就存在一個問題——當我們快速切換的時候,canplay事件觸發產生的相關操作可能在1s內就完成,也就是說,有可能先執行audio.pause()再執行watch時的audio.play(),所以就導致顯示為暫停,但是它歌曲仍然在播放。
解決:因為我們是延時執行,但是在切換的時候,currentSong是快速變化的,我們要保證setTimeout裡的邏輯只執行一次。
clearTimeout(this.timer); this.timer = setTimeout(() => { this.$refs.audio.play().catch((error) => { this.togglePlaying(); // eslint-disable-next-line no-alert alert('播放出錯,暫無該歌曲資源'); }, 1000); // 這裡不直接呼叫currentSong.getLyric() this.getLyric();
這樣就可以保證無論currentSong變化多少次,只執行最後一次的setTimeout的,之前的setTimeout都會被清除掉。
但是光有這個邏輯也是不夠的,還要修改ready的觸發事件canplay改為play,就不能很快切換,保證先執行play才會觸發ready,然後audio.pause肯定在這之後執行。
<audio ref="audio" :src="currentSong.url" @play="ready" @error="error" @timeupdate="updateTime" @ended="end"></audio>
Two.
缺陷:在多次切換過程中,還有可能出現歌詞混亂對應不上歌曲的問題。
原因:因為getLyric方法是非同步操作,當它執行到回撥獲取歌詞的時候我們就有可能切換到下一首歌了,之前的歌詞又會被new一次,相當於new了兩次。
解決:我們要加個判斷:當前的歌詞內容是否等於獲取到的歌詞內容,如果相等就什麼都不做。這樣就保證了歌詞不會亂掉。
this.currentSong.getLyric().then((lyric) => { if (this.currentSong.lyric !== lyric) { return; } this.currentLyric = new Lyric(lyric, this.handleLyric); if (this.playing) { this.currentLyric.play(); } }).catch(() => { this.currentLyric = null; this.playingLyric = ''; this.currentLineNum = 0; });
Three.
缺陷:如果當前播放列表只有一首歌的時候,點下一首,按鈕不會再觸發ready。
原因:列表長度為1時,會呼叫loop方法,loop會把currentTime切到開始,play事件就不會觸發了。
解決:在呼叫loop時直接return。
next() { // 如果沒有ready好的話就直接返回 if (!this.songReady) { return; } if (this.playlist.length === 1) { this.loop(); return; } else { ...... } this.songReady = false; },