VUE移动端音乐APP学习【二十七】:player内核的修改优化

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;
    },
posted @ 2021-07-13 23:04  小风车吱呀转  阅读(103)  评论(0编辑  收藏  举报