Javascript ES6&x2B;React组件实例方法
我正在React中制作一个小的Javascript ES6&x2B;React组件实例方法,javascript,html,reactjs,ecmascript-6,Javascript,Html,Reactjs,Ecmascript 6,我正在React中制作一个小的Video组件(你猜是在播放视频),我想将该组件嵌入父组件中,然后能够调用视频组件上的play方法 我的视频组件看起来像: import React, { Component, PropTypes } from 'react'; import ReactDOM from 'react-dom'; const { string, func } = PropTypes; export default class Video extends Component {
Video
组件(你猜是在播放视频),我想将该组件嵌入父组件中,然后能够调用视频组件上的play
方法
我的视频组件看起来像:
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
const { string, func } = PropTypes;
export default class Video extends Component {
static propTypes = {
source: string.isRequired,
type: string.isRequired,
className: string
};
play = () => {
};
render = () => {
const { className } = this.props;
return (
<video className={ className } width="0" height="0" preload="metadata">
<source src={ this.props.source } type={ this.type } />
Your browser does not support the video tag.
</video>
);
};
}
但是,如果我记录.play
,它是未定义的
接下来,我尝试将play
声明为Video
中的道具,并放置一个默认道具,如:
static defaultProps = {
play: () => {
const node = ReactDOM.findDOMNode(this);
}
}
但是在这个上下文中,这个
是未定义的
在React ES6类上公开函数以便外部组件调用它的正确方法是什么?我是否应该将某些内容附加到
Video.prototype
?您可以使用refs将方法从子对象传递给其父对象
export default class Page extends Component {
video = (
<Video source="some_url" ref="video" type="video/mp4" />
);
render = () => {
<div onClick={ this.refs.video.play } />
}
}
导出默认类页扩展组件{
视频=(
);
渲染=()=>{
}
}
从调用子组件的实例方法的正确方法是不要这样做。:-) 这里有很多资源讨论了原因,但总结一下:它创建了一个不明确的数据流,它将组件耦合在一起,从而减少了关注点的分离,并且更难测试 做您想做的事情的最好方法是使用外部服务(例如事件发射器)来管理状态。在不断变化中,这些将是“商店”。
视频
组件将根据其当前状态触发操作(例如,播放\u已启动
),从而更新存储。页面
组件可以触发开始播放
操作,这也会更新存储。这两个组件都会侦听存储状态中的更改,并做出相应的响应。例如:
Page -> START_PLAYBACK -> Video (play) -> PLAYBACK_STARTED -> Page (update ui)
这里不需要通量(例如,您可以使用Redux或什么都不需要)。这里重要的是一个清晰的、单向的数据流。Hmm这很有趣。所以我这样做了,当它是
onClick={this.refs.video.play}
时,它会因为一些奇怪的原因崩溃,但是当我将play
函数包装到另一个函数中时,一切正常。它崩溃是因为它将click事件传递给play方法。相反,应该有一个click处理程序方法来调用play方法,这就是您所做的。最好更新答案以反映这些注释。i、 例如,this.refs.video.play}/>
是的,我正在使用Redux和React-Redux连接组件。因此,最好的方法是将保存视频的容器组件连接到redux存储,当我想播放视频时,只需发送一个动作。还有一个单独的暂停动作等等。在我看来,这是最好的方式。这看起来有点麻烦(对于一个小应用来说,可能是),但当你的应用扩展得更大一点时,它会更干净。例如,您以后可能希望自动暂停视频,以响应不相关的用户操作(例如打开菜单)。你可以通过参考文献来传递这个方法,但这是混乱和不清楚的。发送一个动作会更好——设置它,然后忘记它。嗯,有趣的是,我更喜欢这个流程。然后,视频组件将只调用由其父组件定义的道具上的函数,然后父组件可以执行它们想要的任何操作,例如执行分派。而仅仅为了播放某个视频而发布一个动作也不难。理论上,你可以将视频源存储为redux存储中的currentVideosPlaying
,然后在连接的组件中进行匹配。我肯定认为这是最好的方法。我不介意使用另一个答案中建议的ref
版本,因为它当然可以正常工作,但对于大型应用程序来说,它是一个混乱的体系结构。
Page -> START_PLAYBACK -> Video (play) -> PLAYBACK_STARTED -> Page (update ui)