ReactJS - 处理子事件处理程序中的父事件

时间:2016-07-04 06:23:33

标签: javascript reactjs javascript-events

我有一个反应容器,我想捕获mousemove事件。这很简单。此外,我有一个由容器呈现的react子组件,其中实际上是mousemove事件处理程序的逻辑所在。所以我需要将mousemove事件从容器父项传递/委托给子项,并获取调用的子项的mousemove处理程序。怎么做得好?

我需要在容器而不是子组件中捕获鼠标事件,因为容器是DOM中较大的HTML元素,我需要捕获整个区域中的事件。

mousemove-handler-logic需要在子组件中,因为它封装了容器不应该知道的一些功能。

容器的render方法:

render() {
    return (
        <div data-component="MyContainer"
             onMouseMove={(event) => this.handleMousemove(event)}>

            <MySubComponent {// ... give some props here}>
        </div>
    );
}

我尝试了一种方法,其中MyContainer为MySubComponent设置回调函数以检索其DOM节点并使用addEventListener注册处理程序但是由于DOM节点偶尔未定义而无法一致地工作:

export default class MyContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {};

        this.getContainerRef = this.getContainerRef.bind(this);
    }

    getContainerRef() {
        return this.refs['containerWrap'];
    }

    render() {
        return (
            <div data-component="MyContainer"
                 ref="containerWrap"
                 onMouseMove={(event) => this.handleMousemove(event)}>

                <MySubComponent getContainerRef={this.getContainerRef} />
            </div>
        );
    }
}

export default class MySubComponent extends Component {
    constructor(props) {
        // ... init something

        this.handleMousemove = this.handleMousemove.bind(this);
    }

    componentDidMount() {
        // add event listener for parent application frame
        let containerDOM = this.props.getContainerRef();
        containerDOM.addEventListener('mousemove', this.handleMousemove, false);
    }

    componentWillUnmount() {
        // remove event listener from parent application frame
        let containerDOM= this.props.getContainerRef();
        containerDOM.removeEventListener('mousemove', this.handleMousemove, false);
    }

    handleMousemove(event) {
        // handle the event
    }

    // ... more methods
} 

我还尝试通过this.refs.SubComponent.handleMousemove直接从MyContainer调用MySubComponent中的mousemove事件处理程序,但这在react-redux中被认为是不好的做法。

2 个答案:

答案 0 :(得分:5)

如果可能,应避免使用refs

如果要捕获父容器中的onMouseMove,我认为最好只将event的相关属性传递给子组件。当父组件componentWillReceiveProps中的值发生变化时,子组件中的shouldComponentUpdate会被调用,您可以对其做出反应。

class Container extends React.Component{
  constructor(props) {
    super(props);
      this.state = {
        mouseX: 0,
        mouseY: 0
      };
    }
  handleMouse(event) {
    event.preventDefault();
    this.setState({
      mouseX: event.clientX,
      mouseY: event.clientY
    });
  }

  render() {
    return <div onMouseMove={(event) => this.handleMouse(event)} className="demo">
        <Child x={this.state.mouseX} y={this.state.mouseY} />
    </div>;
    }
}

你的孩子组成部分:

class Child extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return this.handleMouseMove(nextProps.x, nextProps.y);
  }
  handleMouseMove(x, y) {
    if (x < 150) { // return true to invoke render for some conditions
      // your code
      return true;
    }  
    return false;
  }

  render() {
    return <div>Child Component</div>;
  }
}

但是,您在子组件中的实现将如下所示。它只需知道它的props而不知道它的父组件。

响应组件生命周期:https://facebook.github.io/react/docs/component-specs.html

答案 1 :(得分:0)

虽然你的mousemove应该在子组件中,你的容器应该使用mapDispatchtoProps,就像这样

const mapDispatchToProps = (dispatch) => {
  return {
    onmousemoveAction: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

并在您的子组件调度(onmousemoveAction)

但是,如果您仍想在子组件中使用逻辑

this.refs.mysubcomponent.dispatchEvent(new Event('mousedown'))