Web前端之路让前端飞

绑定事件

2017-02-16  本文已影响56人  编码的哲哲

在react的elements上绑定事件和在dom上绑定事件极为相似,但是还是有一些语法上的不同:
** react的事件用驼峰命名法 ,而不是小写命名法 **
** 你需要传递一个函数名作为一个事件而不是一个字符串 **
比如在传统html中:

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

在react中会有些许不同:

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

另外一个不同是你不能返回一个false去阻止默认事件,你必须调用preventDefault这个函数。比如,在html中,为了去阻止默认的link跳转到其他页面的事件,你可以这样写:

<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去定义一个组件时,一个通用的模式是将一个方法定义为一个事件处理函数。比如,下面这个Toggle组件渲染了一个允许用户切换ON或OFF的按钮:

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

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

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

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

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

你需要注意this在JSX中的含义。在javascript中,类中的方法不是默认是不受绑定的,如果你忘了去显式的绑定并且将其传递给onClick事件,this将会被当作未定义,当这个类函数被执行的时候。
这不是react的原因,而是javascript本身设计的原因* 【如果你有疑惑,推荐你看看《你不知道的javascript上卷》】*。通常,要是你将一个函数名赋值给了一个事件,比如onClick={this.handleClick},这时你就需要显式的绑定它。
如果关于绑定这个问题让你变的困扰的话,这里有两个方法可以让你避免出错:

  1. 使用赋值尖头函数的方式:
class LoggingButton extends React.Component {
  
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
  1. 在element上使用尖头函数绑定:
class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

用第二种方法问题在于不同的回调函数会引发LoggingButton的再次渲染。在大多数情况下,这时极好的特性,但是如果这个会掉函数作为props被传递给子组件呢?这些子组件可能会引发我们不希望的渲染。所以我们建议显示的绑定或者第一种方法,以此来避免性能上的问题。

上一篇 下一篇

猜你喜欢

热点阅读