From 3c50e82a5576a07e853ca0d243a272ca63eaec58 Mon Sep 17 00:00:00 2001 From: "unique.mo" Date: Fri, 15 May 2020 11:23:21 +0800 Subject: [PATCH] perf: use hook for Layout Footer, add requestAnimationFrame --- package.json | 5 +- .../Layout/Footer/AudioTimer/index.tsx | 9 +- .../Layout/Footer/PlayMode/index.tsx | 6 +- .../Layout/Footer/PlayOperations/index.tsx | 24 ++--- .../Layout/Footer/PlayRecord/index.tsx | 36 ++++---- .../Layout/Footer/PlayVolume/index.tsx | 13 +-- .../Layout/Footer/ProgressBar/index.tsx | 25 ++++-- src/components/Layout/Footer/index.tsx | 24 ++--- .../Sidebar/MusicDetail/Lyric/index.tsx | 38 ++++---- .../MusicDetail/Songlists/style.module.css | 2 +- .../Layout/Sidebar/MusicDetail/index.tsx | 88 ++++++++++--------- src/components/ProgressBar/index.tsx | 12 +-- .../Songlists/SonglistItem/index.tsx | 6 +- 13 files changed, 159 insertions(+), 129 deletions(-) diff --git a/package.json b/package.json index 040db66..821e093 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,10 @@ "lyric", "banner", "typescript", - "eslint" + "eslint", + "网易云", + "音乐", + "网易云音乐" ], "author": "", "license": "ISC", diff --git a/src/components/Layout/Footer/AudioTimer/index.tsx b/src/components/Layout/Footer/AudioTimer/index.tsx index d0ed3b8..7d091e9 100644 --- a/src/components/Layout/Footer/AudioTimer/index.tsx +++ b/src/components/Layout/Footer/AudioTimer/index.tsx @@ -3,14 +3,19 @@ import React from 'react' import { AudioContext } from 'reducers/playMusic' import { formatTime } from 'helpers/time' -const { useContext } = React +const { useContext, useMemo } = React const AudioTimer = () => { const audioInfo = useContext(AudioContext) + const { state } = audioInfo + + const time = useMemo(() => { + return `${formatTime(state?.time)} / ${formatTime(state?.duration)}` + }, [state?.time, state?.duration]) return (
- {formatTime(audioInfo?.state?.time)} / {formatTime(audioInfo?.state?.duration)} + {time}
) } diff --git a/src/components/Layout/Footer/PlayMode/index.tsx b/src/components/Layout/Footer/PlayMode/index.tsx index 9bdd438..7d41a24 100644 --- a/src/components/Layout/Footer/PlayMode/index.tsx +++ b/src/components/Layout/Footer/PlayMode/index.tsx @@ -24,14 +24,14 @@ const MODE_MAP: IDictionary<{ } } -const { useContext } = React +const { useContext, useCallback } = React const PlayMode = () => { const dispatch = useContext(PlayMusicDispatchContext) const state = useContext(PlayMusicStateContext) const { playMode } = state - const handleClick = () => { + const handleClick = useCallback(() => { const idx = MODE_ORDER.findIndex(m => m === playMode) const nextMode = MODE_ORDER[(idx + 1) % (MODE_ORDER.length)] @@ -41,7 +41,7 @@ const PlayMode = () => { playMode: nextMode } }) - } + }, [dispatch, playMode]) return ( diff --git a/src/components/Layout/Footer/PlayOperations/index.tsx b/src/components/Layout/Footer/PlayOperations/index.tsx index e232734..b49f84c 100644 --- a/src/components/Layout/Footer/PlayOperations/index.tsx +++ b/src/components/Layout/Footer/PlayOperations/index.tsx @@ -5,25 +5,27 @@ import { PlayMusicStateContext, PlayMusicDispatchContext, AudioContext, ACTIONS import { playList as playListLocalStorage } from 'helpers/play' import styles from './style.module.css' -const { useContext, useMemo } = React +const { useContext, useMemo, useCallback } = React const PlayOperations = () => { const audioInfo = useContext(AudioContext) - const state = useContext(PlayMusicStateContext) + const { state: audioState, controls } = audioInfo + const dispatch = useContext(PlayMusicDispatchContext) + const state = useContext(PlayMusicStateContext) const { musicId } = state const playList = useMemo(() => playListLocalStorage.getItem(), [musicId]) - const togglePlayStatus = () => { - if (audioInfo.state?.paused) { - audioInfo.controls?.play() + const togglePlayStatus = useCallback(() => { + if (audioState?.paused) { + controls?.play() } else { - audioInfo.controls?.pause() + controls?.pause() } - } + }, [audioState?.paused, controls]) - const play = (prev?: boolean) => { + const play = useCallback((prev?: boolean) => { const len = playList.length if (!len) { return @@ -45,10 +47,10 @@ const PlayOperations = () => { music: playList[nextIndex] } }) - } + }, [playList, musicId, dispatch]) - const playPrev = () => play(true) - const playNext = () => play() + const playPrev = useCallback(() => play(true), [play]) + const playNext = useCallback(() => play(), [play]) return ( <> diff --git a/src/components/Layout/Footer/PlayRecord/index.tsx b/src/components/Layout/Footer/PlayRecord/index.tsx index 252ef04..86af2b4 100644 --- a/src/components/Layout/Footer/PlayRecord/index.tsx +++ b/src/components/Layout/Footer/PlayRecord/index.tsx @@ -37,23 +37,25 @@ const PlayRecord: React.FC = ({ show, onClickAway }) => { return (
playRecordRef.current = ref}> -
- {Object.keys(TABS).map((key) => { - return ( -
setActiveTab(TABS[key].tabKey)} - > - {TABS[key].tab} -
- ) - })} -
- -
- {activeTab === TABS.PLAY_LIST.tabKey ? : } -
+ {show && <> +
+ {Object.keys(TABS).map((key) => { + return ( +
setActiveTab(TABS[key].tabKey)} + > + {TABS[key].tab} +
+ ) + })} +
+ +
+ {activeTab === TABS.PLAY_LIST.tabKey ? : } +
+ }
) } diff --git a/src/components/Layout/Footer/PlayVolume/index.tsx b/src/components/Layout/Footer/PlayVolume/index.tsx index 8a1150c..629a9bd 100644 --- a/src/components/Layout/Footer/PlayVolume/index.tsx +++ b/src/components/Layout/Footer/PlayVolume/index.tsx @@ -5,16 +5,19 @@ import ProgressBar from 'components/ProgressBar' import { AudioContext } from 'reducers/playMusic' import styles from './style.module.css' -const { useContext } = React +const { useContext, useMemo, useCallback } = React const PlayVolume = () => { const audioInfo = useContext(AudioContext) + const { state, controls } = audioInfo - const handleBarClick = (percent: number) => { - audioInfo.controls?.volume(percent) - } + const handleBarClick = useCallback((percent: number) => { + controls?.volume(percent) + }, [controls]) - const donePercent = Number((audioInfo.state?.volume || 0).toFixed(2)) + const donePercent = useMemo(() => { + return Number((state?.volume || 0).toFixed(2)) + }, [state?.volume]) return (
diff --git a/src/components/Layout/Footer/ProgressBar/index.tsx b/src/components/Layout/Footer/ProgressBar/index.tsx index 9947161..2f892fa 100644 --- a/src/components/Layout/Footer/ProgressBar/index.tsx +++ b/src/components/Layout/Footer/ProgressBar/index.tsx @@ -4,22 +4,31 @@ import BaseProgressBar from 'components/ProgressBar' import { formatTime } from 'helpers/time' import { AudioContext } from 'reducers/playMusic' -const { useContext } = React +const { useContext, useMemo, useCallback } = React const ProgressBar = () => { const audioInfo = useContext(AudioContext) + const { state, controls } = audioInfo - const donePercent = audioInfo.state?.duration - ? (audioInfo.state?.time / audioInfo.state.duration) - : 0 + const donePercent = useMemo(() => { + return state?.duration + ? (state?.time / state.duration) + : 0 + }, [state?.time, state?.duration]) + + const renderLabel = useCallback(() => { + return formatTime(state?.time) + }, [state?.time]) + + const handleBarClick = useCallback((percent) => { + controls?.seek((state?.duration || 0) * percent) + }, [controls, state?.duration]) return ( formatTime(audioInfo.state?.time)} - onBarClick={(percent) => { - audioInfo.controls?.seek((audioInfo.state?.duration || 0) * percent) - }} + renderLabel={renderLabel} + onBarClick={handleBarClick} /> ) } diff --git a/src/components/Layout/Footer/index.tsx b/src/components/Layout/Footer/index.tsx index 332cecc..900c5fb 100644 --- a/src/components/Layout/Footer/index.tsx +++ b/src/components/Layout/Footer/index.tsx @@ -12,7 +12,7 @@ import PlayVolume from './PlayVolume' import { PlayMusicStateContext, PlayMusicDispatchContext, ACTIONS } from 'reducers/playMusic' import styles from './style.module.css' -const { useContext, useState } = React +const { useContext, useState, useCallback } = React const Footer = () => { const [showPlayRecord, setShowPlayRecord] = useState(false) @@ -20,19 +20,21 @@ const Footer = () => { const state = useContext(PlayMusicStateContext) const { musicId, music, showLyric } = state - const togglePlayRecord = () => setShowPlayRecord(!showPlayRecord) + const togglePlayRecord = useCallback(() => { + setShowPlayRecord(!showPlayRecord) + }, [showPlayRecord, setShowPlayRecord]) - const handleShowLyric = () => { + const handleShowLyric = useCallback(() => { dispatch({ type: ACTIONS.SHOW_LYRIC }) - } + }, [dispatch]) - const handleHideLyric = () => { + const handleHideLyric = useCallback(() => { dispatch({ type: ACTIONS.HIDE_LYRIC }) - } + }, [dispatch]) return (
@@ -83,12 +85,10 @@ const Footer = () => {
- {showPlayRecord && ( - setShowPlayRecord(false)} - /> - )} + setShowPlayRecord(false)} + /> ) } diff --git a/src/components/Layout/Sidebar/MusicDetail/Lyric/index.tsx b/src/components/Layout/Sidebar/MusicDetail/Lyric/index.tsx index 87023d0..462eada 100644 --- a/src/components/Layout/Sidebar/MusicDetail/Lyric/index.tsx +++ b/src/components/Layout/Sidebar/MusicDetail/Lyric/index.tsx @@ -8,7 +8,7 @@ import { formatLyric } from 'helpers/lyric' import { PlayMusicStateContext, AudioContext } from 'reducers/playMusic' import styles from './style.module.css' -const { useEffect, useContext, useRef, useState } = React +const { useEffect, useContext, useRef, useState, useMemo } = React const HIGHLIGHT_LYRIC_TOP = 160 const LYRIC_LINE_HEIGHT = 30 @@ -22,7 +22,7 @@ const Lyric = () => { const { musicId, showLyric } = state const [lyricState, getLyricFn] = useAsyncFn(songApis.getLyric) - const lines = formatLyric(lyricState.value?.lyric) + const lines = useMemo(() => formatLyric(lyricState.value?.lyric), [lyricState.value?.lyric]) useEffect(() => { if (musicId && showLyric) { @@ -32,26 +32,28 @@ const Lyric = () => { useEffect(() => { if (!audioInfo.state?.paused) { - const audioTime = audioInfo.state?.time || 0 + window.requestAnimationFrame(() => { + const audioTime = audioInfo.state?.time || 0 - const lineIndex = lines.findIndex(([time], index) => { - const prevTime = index - 1 >= 0 ? lines[index - 1][0] : time - const nextTime = index + 1 < lines.length ? lines[index + 1][0] : time - if (prevTime <= audioTime && nextTime >= audioTime) { - return true + const lineIndex = lines.findIndex(([time], index) => { + const prevTime = index - 1 >= 0 ? lines[index - 1][0] : time + const nextTime = index + 1 < lines.length ? lines[index + 1][0] : time + if (prevTime <= audioTime && nextTime >= audioTime) { + return true + } + }) + + if (lineIndex > -1) { + const scrollHeight = LYRIC_LINE_HEIGHT * lineIndex - HIGHLIGHT_LYRIC_TOP + lyricRef.current?.scrollTo({ + top: scrollHeight < 0 ? 0 : scrollHeight, + behavior: 'smooth' + }) + setLine(lineIndex) } }) - - if (lineIndex > -1) { - const scrollHeight = LYRIC_LINE_HEIGHT * lineIndex - HIGHLIGHT_LYRIC_TOP - lyricRef.current?.scrollTo({ - top: scrollHeight < 0 ? 0 : scrollHeight, - behavior: 'smooth' - }) - setLine(lineIndex) - } } - }, [audioInfo.state]) + }, [audioInfo.state, lines]) return (
lyricRef.current = ref}> diff --git a/src/components/Layout/Sidebar/MusicDetail/Songlists/style.module.css b/src/components/Layout/Sidebar/MusicDetail/Songlists/style.module.css index 1a24d2a..5776e29 100644 --- a/src/components/Layout/Sidebar/MusicDetail/Songlists/style.module.css +++ b/src/components/Layout/Sidebar/MusicDetail/Songlists/style.module.css @@ -19,5 +19,5 @@ } .playCount { - color: tipsColor; + color: tipsColor !important; } diff --git a/src/components/Layout/Sidebar/MusicDetail/index.tsx b/src/components/Layout/Sidebar/MusicDetail/index.tsx index c7201be..54f6eff 100644 --- a/src/components/Layout/Sidebar/MusicDetail/index.tsx +++ b/src/components/Layout/Sidebar/MusicDetail/index.tsx @@ -34,60 +34,62 @@ const MusicDetail = () => { return (
-
-
-
-
- - -
-
-
- + {showLyric && <> +
+
+
+
+ + +
+
+
+ +
+
-
-
-
-
{music?.name}
-
- 歌手: - {music?.artists.map(({ name }) => name).join(' / ')} -
-
- +
+
{music?.name}
+
+ 歌手: + {music?.artists.map(({ name }) => name).join(' / ')} +
+
+ +
-
-
-
- -
-
- {songlistState.loading || simiSongState.loading ? ( - - ) : ( - <> - {!!songlistState.value?.length && ( +
+
+ +
+
+ {songlistState.loading || simiSongState.loading ? ( + + ) : ( + <> + {!!songlistState.value?.length && ( +
+
包含这首歌的歌单
+
+ +
+
+ )}
-
包含这首歌的歌单
+
相似歌曲
- +
- )} -
-
相似歌曲
-
- -
-
- - )} + + )} +
-
+ }
) } diff --git a/src/components/ProgressBar/index.tsx b/src/components/ProgressBar/index.tsx index 3bd1023..91c4cc1 100644 --- a/src/components/ProgressBar/index.tsx +++ b/src/components/ProgressBar/index.tsx @@ -10,13 +10,13 @@ interface IProps { onBarClick: (donePercent: number) => void } -const { useRef } = React +const { useRef, useCallback, useMemo } = React const ProgressBar: React.FC = ({ donePercent, renderLabel, onBarClick, className }) => { const barRef = useRef() const dotRef = useRef() - const getPercent = (event: React.MouseEvent) => { + const getPercent = useCallback((event: React.MouseEvent) => { const box = barRef.current?.getBoundingClientRect() const clickX = event.pageX - (box?.x || 0) @@ -25,14 +25,14 @@ const ProgressBar: React.FC = ({ donePercent, renderLabel, onBarClick, c : 0 return percent - } + }, []) - const handleBarClick = (event: React.MouseEvent) => { + const handleBarClick = useCallback((event: React.MouseEvent) => { const percent = getPercent(event) onBarClick(percent) - } + }, [getPercent, onBarClick]) - const width = `${donePercent * 100}%` + const width = useMemo(() => `${donePercent * 100}%`, [donePercent]) return (
= ({ id, name, playCount, picUrl }) => { const history = useHistory() - const handleItemClick = () => { + const handleItemClick = useCallback(() => { history.push(`${ROUTES.SONG_LISTS}/${id}`) - } + }, [history, id]) return (