React中的bind

来源:互联网 发布:ubuntu下载jdk1.8 编辑:程序博客网 时间:2024/06/01 10:24

英语原文:
https://facebook.github.io/react/docs/handling-events.html

使用React元素处理事件与处理DOM元素上的事件非常相似。 但至少有3点不同:

  1. React events(事件)使用驼峰式命名,而不是小写。
  2. 使用JSX,您将作为事件处理程序传递一个函数,而不是一个字符串。

HTML

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

React

<button onClick={activateLasers}>  Activate Lasers</button>
  1. 另一个区别是您不能返回false以防止在React中的默认行为。 您必须显式调用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规范定义了这些合成事件,因此您不必担心跨浏览器的兼容性。 请参阅SyntheticEvent参考指南(https://facebook.github.io/react/docs/events.html)了解更多信息。

当使用React时,您通常不需要调用addEventListener来在创建DOM元素之后添加侦听器。 而是在元素最初呈现时提供一个监听器。

当您使用ES6类定义组件时,常见的模式是将事件处理程序作为类上的方法。 例如,该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'));

在JSX回调中你必须要注意 “this”。 在JavaScript中,类方法默认不绑定到对应上下文。 如果您忘记绑定this.handleClick并将其传递给onClick,那么当该函数实际被调用时,这将是未定义的。
这不是react的 特殊行为。
这是是JavaScript中功能如何工作的一部分。
https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/

一般来说,如果你引用一个没有 括号(),的方法,比如onClick = {this.handleClick},你应该绑定该方法,否则报错 undefined

如果在构造函数中绑定每一个方法令你烦恼,有三种方法可以解决这个问题。

方法一

如果您使用实验属性初始化程序语法,则可以使用属性初始化程序来正确绑定回调:(property initializer syntax)
https://babeljs.io/docs/plugins/transform-class-properties/

必须在babel中配置 transform-class-properties

class LoggingButton extends React.Component {  // This syntax ensures `this` is bound within handleClick.  // Warning: this is *experimental* syntax.  handleClick = () => {    console.log('this is:', this);  }  render() {    return (      <button onClick={this.handleClick}>        Click me      </button>    );  }}

方法二

如果您不使用属性初始化程序语法,则可以在回调中使用箭头函数:

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呈现时都会创建一个不同的回调函数。 在大多数情况下,这很好。 但是,如果这个回调作为支持传递给较低的组件,这些组件可能会进行额外的重新渲染。 我们通常建议在构造函数中使用绑定或使用属性initializer语法来避免这种性能问题。

方法三

在render中使用bind

class LoggingButton extends React.Component {  handleClick() {    console.log('this is:', this);  }  render() {    // This syntax ensures `this` is bound within handleClick    return (      <button onClick={this.handleClick.bind(this)}>        Click me      </button>    );  }}

可以看到 React 里面绑定事件的方式和在 HTML 中绑定事件类似,使用驼峰式命名指定要绑定的 onClick 属性为组件定义的一个方法 {this.handleClick.bind(this)}。

注意要显式调用 bind(this) 将事件函数上下文绑定要组件实例上,
缺点与 方法二有相同的性能问题

原创粉丝点击