Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ES6&x2B;React组件实例方法_Javascript_Html_Reactjs_Ecmascript 6 - Fatal编程技术网

Javascript ES6&x2B;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 {

我正在React中制作一个小的
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)