以“React 方式”处理 React 事件:提供事件与将结果提供给回调

IT技术 javascript reactjs events
2021-05-10 02:19:59

在 React 中处理(转储)子组件中的事件时,应该向从其(智能)父组件传递的回调提供什么以使其按预期进行?我们感兴趣的应该是事件还是结果的一部分?当我们有深度嵌套的组件时,它如何扩展?还有其他一些考虑吗?

直观地说,我看到了传递整个事件背后的好处,因为 (i) 在父级中处理它时我们可以从事件中获取更多数据,并且 (ii) 它分离了关注点(转储组件仅呈现并且没有逻辑)。另一方面,它要求孩子拥有bind包装方法的构造函数

我已经看到使用了这两种方法。例如,在Thinking in React 中,作者将回调包装在子组件中以传递值(请参阅 CodePen 上的代码),而在大多数 SO 帖子中,事件被传递并通过event.target.value.

代码示例

通过事件:

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checked: false
    };

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

  handleClick(event) {
    this.setState({checked: event.target.checked});
  }

  render() {
    return (
      <Child checked={this.state.checked} handleClick={this.handleClick}/>
    );
  }
}

class Child extends React.Component {
  render() {
    return (
      <p>
        <input
          type="checkbox"
          checked={this.props.checked}
          onChange={this.props.handleClick}
        />
        {" "}
        Click me
      </p>
    );
  }
}

仅传递值(注意 handleClick2 ):

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checked: false
    };

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

  handleClick(checked) {
    this.setState({checked: checked});
  }

  render() {
    return (
      <Child checked={this.state.checked} handleClick={this.handleClick}/>
    );
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick2 = this.handleClick2.bind(this);
  }

  handleClick2(event) {
    this.props.handleClick(event.target.checked);
  }

  render() {
    return (
      <p>
        <input
          type="checkbox"
          checked={this.props.checked}
          onChange={this.handleClick2}
        />
        {" "}
        Click me
      </p>
    );
  }
}

2个回答

你应该在没有事件的情况下传递你需要的东西。除非您想从事件中提取相关数据,否则不需要整个对象:例如,target当您对多个元素/动作使用相同的回调时。

你不会有任何性能问题,而且绝对没有react式的方法来做到这一点。只用你的判断。

event.target是 Web 平台标准的一部分。例如:

让我们看一个事件如何在树中工作的例子:

<!doctype html>
<html>
 <head>
  <title>Boring example</title>
 </head>
 <body>
  <p>Hello <span id=x>world</span>!</p>
  <script>
   function debug(target, currentTarget, eventPhase)
     {
     console.log("target: " + JSON.stringify(target) );
     console.log("currentTarget: " + JSON.stringify(currentTarget) );
     console.log("eventPhase: " + JSON.stringify(eventPhase) );
     }
     
   function test(e) {
     debug(e.target, e.currentTarget, e.eventPhase)
   }
   
   document.addEventListener("hey", test, true)
   document.body.addEventListener("hey", test)
   var ev = new Event("hey", {bubbles:true})
   document.getElementById("x").dispatchEvent(ev)
  </script>
 </body>
</html>

调试函数将被调用两次。每次事件的目标属性值都会是 span 元素。第一次 currentTarget 属性的值将是文档,第二次是 body 元素。eventPhase 属性的值从 CAPTURING_PHASE 切换到 BUBBLING_PHASE。如果为 span 元素注册了事件侦听器,则 eventPhase 属性的值将是 AT_TARGET。

所以很容易移植到更新可再生的东西

参考