标签:int promise span interface type attr test eset idm
在class 组件中,我们需要在 componentDidMounted 里面给 mp3 加上监听,然后在 组件销毁的时候 去掉监听。
来控制 mp3 的播放和暂停。相对来说比较麻烦。难以抽离。
这里用 hooks 达到完全抽离的效果:
interface IAudioProps extends React.AudioHTMLAttributes<any> {
src: string
}
const wrapEvent = (userEvent:any, proxyEvent?:any) => {
return (event:any) => {
try {
proxyEvent && proxyEvent(event);
} finally {
userEvent && userEvent(event);
}
};
};
const useAudio = (props:IAudioProps)=>{
const ref = useRef< HTMLAudioElement | null >(null)
const [state,setState] = useState({
time: 0,
duration: 0,
paused: true,
muted: false,
volume: 1
});
const onPlay = ()=>{
setState((obj)=>{ return {...obj,paused:false} })
}
const onPause = ()=>{
setState((obj)=>{ return {...obj,paused:true} })
}
const element = React.createElement("audio",{
...props,
ref,
onPlay: wrapEvent(props.onPlay, onPlay),
onPause: wrapEvent(props.onPause, onPause),
onEnded: wrapEvent(props.onEnded, onPause),
})
let lockPlay: boolean = false;
const controls = {
play: () => {
const el = ref.current;
if (!el) {
return undefined;
}
if (!lockPlay) {
const promise = el.play();
const isPromise = typeof promise === ‘object‘;
if (isPromise) {
lockPlay = true;
const resetLock = () => {
lockPlay = false;
};
promise.then(resetLock, resetLock);
}
return promise;
}
return undefined;
},
pause: () => {
const el = ref.current;
if (el && !lockPlay) {
return el.pause();
}
},
seek: (time: number) => {
const el = ref.current;
if (!el || state.duration === undefined) {
return;
}
time = Math.min(state.duration, Math.max(0, time));
el.currentTime = time;
},
volume: (volume: number) => {
const el = ref.current;
if (!el) {
return;
}
volume = Math.min(1, Math.max(0, volume));
el.volume = volume;
setState((obj)=>{ return {...obj,volume} });
},
mute: () => {
const el = ref.current;
if (!el) {
return;
}
el.muted = true;
},
unmute: () => {
const el = ref.current;
if (!el) {
return;
}
el.muted = false;
},
};
return [
<span>
{element}
{
state.paused ? <button onClick={controls.play}>点击播放</button>:<button onClick={controls.pause}>点击暂停</button>
}
</span>,
controls,
ref
] as const
}
使用
const TestState = ()=>{
const [audio,controls,ref] = useAudio({src:"http://cloud.chan3d.com/cdn/website/mp3/1.mp3"})
return (
<div className="test-state">
{audio}
</div>
)
}
使用 React hooks 优雅解决 mp3 的播放 和 暂停
标签:int promise span interface type attr test eset idm
原文地址:https://www.cnblogs.com/muamaker/p/14764062.html