简体   繁体   English

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

[英]ReactJS - Handle parent event in child event handler

I have a react container where I want to capture mousemove events. 我有一个我想捕获mousemove事件的反应容器。 That is pretty straight forward. 这很简单。 Further I have a react sub-component rendered by the container where actually the logic for the mousemove event handler resides. 此外,我有一个由容器渲染的react子组件,该组件实际上是mousemove事件处理程序的逻辑所在。 So I need to pass/delegate the mousemove event from the container parent to the child and get the mousemove handler of the child invoked. 因此,我需要将mousemove事件从容器父级传递/委托给子级,并获取所调用子级的mousemove处理函数。 How is that done properly? 如何正确完成?

I need to capture the mouse event in the container rather than the sub-component because the container is a larger HTML element in the DOM and I need to capture events in that whole area. 我需要在容器而不是子组件中捕获鼠标事件,因为容器是DOM中较大的HTML元素,并且我需要在整个区域中捕获事件。

The mousemove-handler-logic needs to be in the sub-component as it encapsulates some functionality the container should not be aware of. mousemove-handler-logic必须位于子组件中,因为它封装了容器不应该知道的某些功能。

The render method of the container: 容器的渲染方法:

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

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

I tried an approach where MyContainer sets callback functions for MySubComponent to retrieve its DOM Node and register handler with addEventListener but that did not work consistently as occasionally the DOM Node got undefined: 我尝试了一种方法,其中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
} 

I also tried to call the mousemove event handler in MySubComponent directly from MyContainer via this.refs.SubComponent.handleMousemove but that is regarded to be bad practise in react-redux. 我也试图直接从myContainer中通过调用鼠标移动事件处理程序MySubComponent this.refs.SubComponent.handleMousemove但被认为是在反应-终极版不好的做法。

Working with refs should be avoided if possible. 如果可能,应避免使用refs

If you want to capture the onMouseMove in the parent container I think best is to just pass the relevant properties of the event to your child component. 如果要在父容器中捕获onMouseMove ,我认为最好是将event的相关属性传递给子组件。 When the values change in the parent componentWillReceiveProps and shouldComponentUpdate in the child component get invoked and you can react to it. 当父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>;
    }
}

And your Child component: 和您的子组件:

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

However your implementation in the child component will look like. 但是,您在子组件中的实现将如下所示。 It just has to know about its props and nothing about its parent component. 它只需要了解其props而无需了解其父组件。

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

Although your mousemove should be in the subcomponent and your container should use mapDispatchtoProps, like this 尽管您的mousemove应该位于子组件中,并且您的容器应使用mapDispatchtoProps,像这样

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

and in your subcomponent dispatch(onmousemoveAction) 并在您的子组件中调度(onmousemoveAction)

But if you still want to have logic in subcomponent do 但是,如果您仍然想在子组件中包含逻辑,请执行

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM