React核心概念:事件处理

21 篇文章 0 订阅
21 篇文章 1 订阅

上一节:state&生命周期
下一节:条件渲染

React核心概念:事件处理

事件处理函数

处理React元素的事件与处理DOM元素上的事件十分相似,它们仅有一些语法上的区别。

  • React事件名采用小驼峰命名规则而不是纯小写
  • 使用JSX需要传入函数作为事件处理函数而不是传入字符串

例如,在HTML上

 <button onclick="activateLasers()">
  Activate Lasers
</button>

在React中则略微不同

<button onClick={activateLasers}>
  Activate Lasers
</button>

React上的另一个不同之处在于你不能返回false去阻止默认行为,必须显示地调用preventDefault才能阻止默认行为。

在HTML中,为了阻止锚点链接默认打开一个新页面可以这样写:

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>

但是在React中,需要这样写才能阻止打开新页面:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

在这里,e是一个合成事件。React根据W3C规范来定义这些合成事件,所以无需担心浏览器的兼容问题。

使用React时,通常不需要调用addEventListener来为已创建的DOM元素添加监听器。取而代之的是在元素被渲染之初提供一个监听器。

当你定义了一个ES6 class组件时,一个常用的方法是将事件处理器声明为class的一个方法。下面的代码声明了一个Toggle组件,让用户能在ON和OFF两种状态之间切换。

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // 这段代码让this在回调函数中能够有效
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

必须谨慎对待JSX回调函数中的this,在Javascript中,class方法是不会默认绑定this的。如果你忘记绑定this.handleClick并将它传递给onClick,那么当这个方法被调用时浏览器将无法识别this,因为此时thisundefined

这不是React特有的特性,这与JavaScript的工作原理相关。通常来说,如果不在方法后面加上(),比如onClick={this.handleClick},我们就应该绑定它。

如果觉得绑定方法很麻烦,这里有两种选择可以避免绑定。如果你正在使用实验性的public class fields语法,你可以使用class fields正确绑定回调。

class LoggingButton extends React.Component {
  // 这个语法可以确保回调函数已经绑定了this
  // 但请注意这是实验性的语法
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

这种语法在使用Create React App创建的项目中是可以使用的。

如果没有使用class fields语法,那么你可以在回调函数中使用箭头函数。

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 这段代码确保了handleClick绑定了this
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

但是这个语法有一个问题,每当LoggingButton被渲染时都会创建一个不同回调函数。在大多数情况下这是没有问题的,但是如果这个回调函数作为props传递给子组件时,这些组件可能会做一个额外的重新渲染。所以我们通常推荐在构造函数中绑定事件或者使用class fields语法来绑定以避免此类的性能问题。

向事件处理函数传递参数

在循环中我们通常需要传递一个额外的参数给事件处理函数。比如如果id时想要删除的那一行的id,以下两种方法都可以将id传递给事件处理函数。

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上面两行代码是等价的,只不过分别使用了箭头函数Function.prototype.bind

在上面的两个例子中,合成事件e代表了React事件,都作为第二个参数传递给事件处理函数。在箭头函数中我们需要显示地传递e,但是使用bind方法,事件对象以及更多的参数都被隐式地传递。

上一节:state&生命周期
下一节:条件渲染

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值