ES6 + React组件实例方法

时间:2016-01-07 21:04:12

标签: javascript html5 reactjs ecmascript-6

我在React中制作了一个小Video组件(因为你猜对了,播放视频),我希望将该组件嵌入到父组件中,然后能够调用{{1}视频组件上的方法。

我的视频组件如下:

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> ); }; }

Page

但是如果我记录export default class Page extends Component { video = ( <Video source="some_url" type="video/mp4" /> ); render = () => { <div onClick={ this.video.play } /> } } 它未定义。

接下来,我尝试将.play声明为play中的道具,然后设置默认道具:

Video

但在此上下文中,static defaultProps = { play: () => { const node = ReactDOM.findDOMNode(this); } } 未定义。

在React ES6类上公开函数以便外部组件可以调用它的正确方法是什么?我应该附加某些内容到this吗?

2 个答案:

答案 0 :(得分:6)

调用子组件的实例方法的正确方法是不执行此操作。 : - )

这里有很多资源可以讨论为什么,但总结一下:它创建了一个不清楚的数据流,它将组件耦合在一起,减少了关注点的分离,并且更难以测试。

执行所需操作的最佳方法是使用外部服务(例如事件发射器)来管理状态。在Flux中,这些将是&#34; store&#34;。 Video组件将根据其当前状态(例如PLAYBACK_STARTED)触发操作,这反过来会更新商店。 Page组件可以触发START_PLAYBACK操作,这也会更新商店。两个组件都会监​​听商店状态的变化,并做出相应的响应。 E.g:

Page -> START_PLAYBACK -> Video (play) -> PLAYBACK_STARTED -> Page (update ui)

此处不要求Flux(例如,您可以使用Redux或根本不使用任何内容)。这里重要的是清晰的单向数据流。

答案 1 :(得分:2)

您可以使用refs将方法从子级传递给其父级。

export default class Page extends Component {
    video = (
        <Video source="some_url" ref="video" type="video/mp4" />
    );

    render = () => {
        <div onClick={ this.refs.video.play } />
    }
}

来自Expose Component Functions