首页 文章

ES6反应组件实例方法

提问于
浏览
3

我正在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>
    );
  };
}

它真的很简单,没有什么花哨的东西在这里 .

现在在父组件中,我们称之为 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);
    }
}

但在这种情况下, this 未定义 .

在React ES6类上公开函数以便外部组件可以调用它的正确方法是什么?我应该附上一些东西吗? Video.prototype

2 回答

  • 6

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

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

    做你想做的事情的最好方法是使用外部服务(例如事件 Launcher )来管理状态 . 在Flux中,这些将是"stores" . Video 组件将根据其当前状态(例如 PLAYBACK_STARTED )触发操作,这反过来会更新商店 . Page 组件可以触发 START_PLAYBACK 操作,这也会更新商店 . 两个组件都会侦听商店状态的变化,并做出相应的响应 . 例如 . :

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

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

  • 3

    您可以使用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

相关问题