本节代码对应 GitHub 分支: chapter9

仓库传送门 (opens new window)

# 1. 出现 mini 播放器时页面底部被遮挡

问题如图:

当 mini 播放器不出现的时候,还能够正常看到底部,但一出现,最下面就被遮住了,每个页都是如此。为什么?因为之前布局都是用 bottom: 0,但是在 mini 播放器出现后我们需要 改变这个 bottom 值,miniPlayer 高度为 60px,我们把 bottom 设为 60px,等于把下面的 60px 高度留给播放器。

因此对于每个页面 Container 的 bottom 值有无播放器需要分开处理。那怎么判断有无播放器出现呢?

有一个很简单的方式,就是判断当前 playList 的长度,如果大于 0 则正在播放,等于 0 则没有。

以 Recommend 组件为例:

function Recommend (props){
  const { songsCount } = props;
  //...

  <Content play={songsCount}>
  //...
}

const mapStateToProps = (state) => ({
  //...
  songsCount: state.getIn (['player', 'playList']).size,// 尽量减少 toJS 操作,直接取 size 属性就代表了 list 的长度
});
//...

相应 style.js 中:

import styled from'styled-components';

export const Content = styled.div`
  position: fixed;
  top: 90px;
  bottom: ${props => props.play > 0?"60px": 0};
  width: 100%;
`

然后在 Singer、Singers、Rank、Album 组件中也是相同的操作,这里就不浪费篇幅了。大家可以自行完成,也可以参考 chapter8 分支的代码。

# 2. 频繁切歌导致的异常

如果频繁切换歌曲,会出现这样的异常:

image-20210215204015438

操作过快直接报错,这是完全无法接受的。所以我们必须究根溯源,把这个问题给解了。

解决的原理:其实从 audio 标签拿到 src 加载到能够播放之间有一个缓冲的过程,只有当控件能够播放时才能够切到下一首。如果在这个缓冲过程中切歌就会报错。

现在就来具体地来解决这个问题:

//Player/index.js
const songReady = useRef (true);

useEffect (() => {
  if (
    !playList.length ||
    currentIndex === -1 ||
    !playList [currentIndex] ||
    playList [currentIndex].id === preSong.id ||
    !songReady.current// 标志位为 false
  )
    return;
  let current = playList [currentIndex];
  setPreSong (current);
  songReady.current = false; // 把标志位置为 false, 表示现在新的资源没有缓冲完成,不能切歌
  changeCurrentDispatch (current);// 赋值 currentSong
  audioRef.current.src = getSongUrl (current.id);
  setTimeout (() => {
    // 注意,play 方法返回的是一个 promise 对象
    audioRef.current.play ().then (() => {
      songReady.current = true;
    });
  });
  togglePlayingDispatch (true);// 播放状态
  setCurrentTime (0);// 从头开始播放
  setDuration ((current.dt/ 1000) | 0);// 时长
}, [playList, currentIndex]);

同时再做一下异常处理:

const handleError = () => {
  songReady.current = true;
  alert ("播放出错");
};

<audio
  //...
  onError={handleError}
></audio>

这样就能放心切歌,不会有报错啦!

阅读全文