播放器 - 最佳实践
避免 <Player> 的重新渲染
🌐 Avoid re-renders of the <Player>
以下模式不是理想的,因为每次时间更新时,<Player> 都会被重新渲染:
🌐 The following pattern is not ideal because every time the time updates, the <Player> is being re-rendered:
❌ Problematicexport constApp :React .FC = () => { constplayerRef =useRef <PlayerRef >(null); const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ('timeupdate', (e ) => {setCurrentTime (e .detail .frame ); }); }, []); return ( <div > <Player ref ={playerRef }component ={MyVideo } {...otherProps } /> <div >Current time: {currentTime }</div > </div > ); };
我们建议将你的控件和用户界面呈现为渲染 <Player> 的组件的同级,并将播放器的引用作为 prop 传递:
🌐 We advise to render your controls and UI as a sibling to the component that renders the <Player> and pass a ref to the player as a prop:
✅ BetterconstPlayerOnly :React .FC <{playerRef :React .RefObject <PlayerRef | null>; }> = ({playerRef }) => { return <Player ref ={playerRef }component ={MyVideo } {...otherProps } />; }; constControlsOnly :React .FC <{playerRef :React .RefObject <PlayerRef | null>; }> = ({playerRef }) => { const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ('timeupdate', (e ) => {setCurrentTime (e .detail .frame ); }); }, []); return <div >Current time: {currentTime }</div >; }; export constApp :React .FC = () => { constplayerRef =useRef <PlayerRef >(null); return ( <> <PlayerOnly playerRef ={playerRef } /> <ControlsOnly playerRef ={playerRef } /> </> ); };
这性能更高,因为 <Player> 被重新渲染的次数更少。
🌐 This is much more performant because the <Player> gets rerendered less often.
这个建议主要针对像当前时间这样经常更新的状态。在父组件中保持像 loop 切换这样的状态是可以的,因为它不需要频繁变化。
🌐 This advice is mainly for frequently updated state like the current time. Keeping state like a loop toggle in the parent component is fine, because it is not expected to change frequently.
将用户交互事件传递给 play()
🌐 Pass the user interaction event to play()
当你监听一个 onClick() 事件时,浏览器会给你一个 event 参数。
将它传递给 .play() 和 .toggle(),可以最大限度地降低触发浏览器可能施加的自动播放限制的几率。
🌐 When you listen to an onClick() event, the browser will give you an event argument.
Pass it on to .play() and .toggle() to have the lowest chance of hitting autoplay restrictions that the browser may impose.
记忆化 inputProps
🌐 Memoize the inputProps
不对 inputProps 进行记忆化可能会导致整个树重渲染过多次,从而造成瓶颈。
🌐 Not memoizing the inputProps can cause the whole tree to re-render too many times and create a bottleneck.
Player.tsximport {Player } from '@remotion/player'; import {useState ,useMemo } from 'react'; import {MyVideo } from './remotion/MyVideo'; export constApp :React .FC = () => { const [text ,setText ] =useState ('world'); constinputProps =useMemo (() => { return {text , }; }, [text ]); return ( <Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={inputProps } /> ); };
另请参阅
🌐 See also