reactjs – 如何将操作传递给React组件
虽然我的场景非常具体,但我认为它在Flux中提出了一个更大的问题.组件应该是来自商店的简单数据呈现,但是如果组件呈现有状态的第三方组件会怎样?如何在遵守Flux规则的同时与第三方组件进行交互?
所以,我有一个包含视频播放器的React应用程序(使用clappr).一个很好的例子就是寻求.当我点击进度条上的某个位置时,我想要寻找视频播放器.这就是我现在所拥有的(使用RefluxJS).我试图将我的代码删除到最相关的部分. var PlayerActions = Reflux.createActions([ 'seek' ]); var PlayerStore = Reflux.createStore({ listenables: [ PlayerActions ],onSeek(seekTo) { this.data.seekTo = seekTo; this.trigger(this.data); } }); var Player = React.createClass({ mixins: [Reflux.listenTo(PlayerStore,'onStoreChange')],onStoreChange(data) { if (data.seekTo !== this.state.seekTo) { window.player.seek(data.seekTo); } // apply state this.setState(data); } componentDidMount() { // build a player window.player = new Clappr.Player({ source: this.props.sourcePath,chromeless: true,useDvrControls: true,parentId: '#player',width: this.props.width }); },componentWillUnmount() { window.player.destroy(); window.player = null; },shouldComponentUpdate() { // if React realized we were manipulating DOM,it'd certainly freak out return false; },render() { return <div id='player'/>; } }); 我对此代码的错误是当你试图两次寻找同一个地方时.想象一下视频播放器在不断播放.点击进度条进行搜索.不要移动鼠标,等待几秒钟.再次点击与之前相同位置的进度条. data.seekTo的值没有改变,因此第二次不调用window.player.seek. 我已经考虑过一些解决这个问题的可能性,但我不确定哪个更正确.请求输入… 1:使用后重置seekTo 简单地重置seekTo似乎是最简单的解决方案,尽管它肯定不再优雅.最终,这更像是一个创可贴. 这就像……一样简单 window.player.on('player_seek',PlayerActions.resetSeek); 2:创建一个单独的商店,更像是一个传递 基本上,我会听SeekStore,但实际上,这将作为传递,使其更像是商店的动作.这个解决方案感觉就像是Flux的黑客,但我认为它会起作用. var PlayerActions = Reflux.createActions([ 'seek' ]); var SeekStore = Reflux.createStore({ listenables: [ PlayerActions ],onSeek(seekTo) { this.trigger(seekTo); } }); var Player = React.createClass({ mixins: [Reflux.listenTo(SeekStore,onStoreChange(seekTo) { window.player.seek(seekTo); } }); 3:在我的行动中与window.player交互 当我想到它时,这感觉是正确的,因为调用window.player.seek实际上是一个动作.唯一奇怪的是,我感觉不正确与行动中的窗口交互.也许这只是一种非理性的想法. var PlayerActions = Reflux.createActions({ seek: {asyncResult: true} }); PlayerActions.seek.listen(seekTo => { if (window.player) { try { window.player.seek(seekTo); PlayerActions.seek.completed(err); } catch (err) { PlayerActions.seek.failed(err); } } else { PlayerActions.seek.failed(new Error('player not initialized')); } }); 顺便说一句,房间里还有另一头大象,我没有碰过.在我的所有示例中,播放器都存储为window.player. Clappr在旧版本中自动执行此操作,但虽然已经修复了它与Browserify一起使用,我们继续将其存储在窗口(技术债务).显然,我的第三个解决方案是利用这个事实,从技术上来说这是一件坏事.无论如何,在任何人指出,理解和注意之前. 4:通过dispatchEvent寻求 我也明白,派遣一个自定义事件可以完成工作,但考虑到我有Flux,这感觉有点不对劲.这感觉就像我要在我的Flux架构之外完成工作.我应该能够做到并留在Flux游乐场内. var PlayerActions = Reflux.createActions({ seek: {asyncResult: true} }); PlayerActions.seek.listen(seekTo => { try { let event = new window.CustomEvent('seekEvent',{detail: seekTo}); window.dispatchEvent(event); PlayerActions.seek.completed(err); } catch (err) { PlayerActions.seek.failed(err); } }); var Player = React.createClass({ componentDidMount() { window.addEventListener('seekEvent',this.onSeek); },componentWillUnmount() { window.removeEventListener('seekEvent',onSeek(e) { window.player.seek(e.detail); } }); 解决方法
5:保持比赛状态(如
Dan Kaufman所示)
可以这样做: handlePlay () { this._interval = setInterval(() => this.setState({curPos: this.state.curPos + 1}),1000) this.setState({playing: true}) // might not be needed } handlePauserOrStop () { clearInterval(this._interval) this.setState({playing: false}) } componentWillUnmount () { clearInteral(this._interval) } onStoreChange (data) { const diff = Math.abs(data.seekTo - this.state.curPos) if (diff > 2) { // adjust 2 to your unit of time window.player.seek(data.seekTo); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |