react中这几种定义函数的方式,有什么区别呢?

// 写法一
export default class App extends React.Component {
    tableHeader = () => {};
}
// 写法二
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.tableHeader = this.tableHeader.bind(this);
    }
    tableHeader() {
    };
}
// 写法三
export default class App extends React.Component {

    tableHeader() {
    };
}

我在看其他人的代码时,发现有上面这几种方法,都有什么区别啊,我纠结了好几天了.上网找了下,也没看出所以然,如果想弄懂,该看哪些资料呢


上面的第二种写法我是不能接受,太繁琐了.
我是否可以理解为,下面两种下法是等价的呢.
我一般都是使用下面的第五种写法,但是有同事和我说写法四会比较好,性能方面会好些,但是我理解的,这两种写法效果是一样的,不存在性能不同的问题

// 写法四
class  App extends React.Component {
  constructor(props) {
    super(props);
  }
  handleClick= ()=>{
  }
  render() {
    return (
      <button onClick={this.handleClick}>点击</button>
    );
  }
}
// 写法五
export default class App extends React.Component {
    handleClick() {
    };
    render(){
        return (
        <button onClick={()=> {this.handleClick();}}>点击</button>
        );
    }
}

我说下我喜欢第五种的原因,因为有时候我会这样写,这样写法比较简单,并且也可以达到函数复用.
抱歉,一个问题修改了这么多次?

export default class App extends React.Component {
    handleClick(type) {
     console.log(`获取${type}数据`);
    };
    render(){
        return (
        <div>
         <button onClick={()=> {this.handleClick('header');}}>获取顶部数据</button>
         <button onClick={()=> {this.handleClick('footer');}}>获取底部数据</button>
        </div>
        );
    }
}
阅读 5.2k
5 个回答

主要是函数内this指向不同

第一种写法还不是js标准,但是babel已经支持了。相当于让tableHeader的值为一个箭头函数,而箭头函数的特性我们都知道:它内部没有this,它会使用定义时的this,这里this就会指向这个类的实例。

第二种写法它的目的和第一种是一样的,让函数内部的this指向这个类的实例,它是用bind实现的,bind的第一个参数表示context,就是this。

第三种写法就是普通的写法,之所以会有前面两种写法,就是因为第三种写法可能会出问题。

举个简单的例子,按第三种方式写:

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

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

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

这段代码实际上是不能工作的,因为handleClick内部用到了this.setState,而handleClick执行时,this是undefined

如果想要它工作,可以改成前两种的写法,或者这样改:

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

用一个箭头函数将其包裹住

写法一与写法三一样。不同的是写法一的functionES6中的箭头函数,写法三是常见的function.
写法二呢,添加了一个classconstructor函数。
jsclass默认无this,所以我们通常在constructor中将父类的this引入,然后bind到该类的方法中。但是,ES6中的() => {} //箭头函数,默认会带this,也不会有闭包,所以写法一中的tableHeader 是有this的,写法三中的没有。

我也补充一下
你需要去看this关键字的相关内容。
你后面问道我是否可以理解为,下面两种下法是等价的呢.
其实不是等价的,因为第二种每次render都是会重新创建个function去包裹handleClick,这很浪费,也对性能不利。在JSX中使用.bind(this)也是一样的,你可以看下jsx-no-bind

我也是新手,但是恰好大概知道这几种用法
第一种写法和第二种写法等同,可以理解为第一种写法是语法糖

第三种的话
你render的时候用this.tableHeader()无法调用,需要先bind(),而第一种写法的话相当于已经bind过

楼上说得很对, 补充下:
打铁还要自身硬!
虽然写法有这么多, 但还是要去学习下ES6的一些基础知识, 否则晓得这些用法也无用.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题