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

Javascript ReactJS-在子事件处理程序中处理父事件,javascript,reactjs,javascript-events,Javascript,Reactjs,Javascript Events,我有一个react容器,我想在其中捕获mousemove事件。这很直截了当。此外,我还有一个由容器呈现的react子组件,mousemove事件处理程序的逻辑实际上驻留在该容器中。因此,我需要将mousemove事件从容器父容器传递/委托给子容器,并获取调用的子容器的mousemove处理程序。如何正确地做到这一点 我需要捕获容器中的鼠标事件,而不是子组件,因为容器是DOM中一个较大的HTML元素,我需要捕获整个区域中的事件 mousemove处理程序逻辑需要位于子组件中,因为它封装了容器不应该

我有一个react容器,我想在其中捕获mousemove事件。这很直截了当。此外,我还有一个由容器呈现的react子组件,mousemove事件处理程序的逻辑实际上驻留在该容器中。因此,我需要将mousemove事件从容器父容器传递/委托给子容器,并获取调用的子容器的mousemove处理程序。如何正确地做到这一点

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

mousemove处理程序逻辑需要位于子组件中,因为它封装了容器不应该知道的一些功能

容器的渲染方法:

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

            <MySubComponent {// ... give some props here}>
        </div>
    );
}
render(){
返回(
this.handleMousemove(事件)}>
);
}
我尝试了一种方法,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
} 
导出默认类MyContainer扩展组件{
建造师(道具){
超级(道具);
this.state={};
this.getContainerRef=this.getContainerRef.bind(this);
}
getContainerRef(){
返回此.refs['containerWrap'];
}
render(){
返回(
this.handleMousemove(事件)}>
);
}
}
导出默认类MySubComponent扩展组件{
建造师(道具){
//…是什么
this.handleMousemove=this.handleMousemove.bind(this);
}
componentDidMount(){
//为父应用程序框架添加事件侦听器
让containerDOM=this.props.getContainerRef();
containerDOM.addEventListener('mousemove',this.handleMousemove,false);
}
组件将卸载(){
//从父应用程序框架中删除事件侦听器
让containerDOM=this.props.getContainerRef();
containerDOM.removeEventListener('mousemove',this.handleMousemove,false);
}
handleMousemove(事件){
//处理事件
}
//…更多方法
} 

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

尽管您的mousemove应该在子组件中,并且您的容器应该使用mapDispatchtoProps,就像这样

const mapDispatchToProps = (dispatch) => {
  return {
    onmousemoveAction: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}
在您的子组件分派中(onmousemoveAction)

但如果您仍然希望在子组件中包含逻辑,请执行以下操作

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

如果可能,应避免使用参考文件
refs

如果您想在父容器中捕获
onMouseMove
,我认为最好的方法是将
事件的相关属性传递给您的子组件。当父
组件中的值更改时,将调用子组件中的willreceiveprops
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>;
    }
}
类容器扩展React.Component{
建造师(道具){
超级(道具);
此.state={
鼠标:0,
老鼠:0
};
}
搬运室(活动){
event.preventDefault();
这是我的国家({
mouseX:event.clientX,
老鼠:event.clientY
});
}
render(){
返回此.handleMouse(事件)}className=“demo”>
;
}
}
和您的子组件:

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>;
  }
}
类子级扩展React.Component{
shouldComponentUpdate(下一步,下一步状态){
返回这个.handleMouseMove(nextrops.x,nextrops.y);
}
把手移动(x,y){
如果(x<150){//返回true以调用某些条件的渲染
//你的代码
返回true;
}  
返回false;
}
render(){
返回子组件;
}
}
但是,您在子组件中的实现看起来是这样的。它只需要知道它的
道具
,而不需要知道它的父组件


反应组件生命周期:

您的问题与redux无关。您能否让
MySubComponent
直接处理
onMouseMove
事件?如果逻辑完全由
MySubComponent
处理,那么就更有意义了。您能给出第一种方法的代码吗?这样我们就可以了解出了什么问题?@xiaofan2406:请看我对这个问题的编辑。我需要在大型HTML容器元素上捕获事件,而不是在非常小的子组件上捕获事件。@DamienLeroux:我添加了代码。您可以看到,我提供了一个回调函数
getContainerRef
MySubComponent
,在这里它可以检索容器的DOM ref并注册事件处理程序本身。但是,当容器卸载时,提供的ref始终变为未定义,并且无法删除事件处理程序。