箭头函数内自动继承了上下文语义中的this对象;
在点引用直接调用中,引用对象this指针也会自动传递到被引用方法中。但点引用、引用调用和箭头函数同时出现时,容易混淆,我们把合法的写法做一个总结。我们先来看一段计时器示例:我们把index.html放在/public文件夹下,把index.js,app.js,及全局样式表index.css放在/source中:
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; class Counter extends React.Component { constructor(props) { super(props); this.state={count: 0};//状态对象初始化状态 } ()=>Count() { this.setState({count: this.state.count+1}); } render() { return (<div><h2>The Count is {this.state.count}</h2><p><button onClick={this.Count}>+1</button></p></div>); } } class Clocker extends React.Component { constructor(props) { super(props);//调用React.Component构造函数,此后this建立 this.state={date:new Date()};//状态对象初始化状态,仅能出现在状态函数中 } componentDidMount() { this.timerId=setInterval(()=>this.tick(),1000); //默认单位为毫秒,即每隔1s立即调用this.tick方法 } componentWillUnmount() { clearInterval(this.timerId); } tick() { this.setState({date:new Date()}); } render() { return (<div><p>The time is {this.state.date.toLocaleTimeString()}</p></div>); } } const test=ReactDOM.createRoot(document.getElementById("test")); const root=ReactDOM.createRoot(document.getElementById("root")); root.render(<Clocker/>); test.render(<Counter/>);
|
为什么Clocker类方法tick()是普通函数,而Counter类方法Count必须是箭头函数呢?
写法1:
<button onClick={this.Counter}>,Counter()必须为箭头函数。这是一个引用调用,在执行主函数React.render()时,由于只是取出Counter函数,不会发生死循环。
写法2:
<button onClick={()=>this.Counter()}>这是一个匿名箭头函数,内部采用直接引用,因此在点击时不会出现“裸引用”,Counter既可以是普通函数,也可以是箭头函数。render继承当前实例的this,箭头函数内部继承render的this,Counter函数内部继承引用对象,即箭头函数里的this,不会出现undefined。
错误写法:<button onClick={this.Counter()},这种情况下,编译时会出现render()->Counter()->setState()->render()死循环
错误写法:<button onClick={()=>this.Count},这种情况下,不会死循环,但点击无反应,因为箭头函数内部是引用调用。
错误写法:<button onCLick={this.Count},且Count为普通函数。这种情况下,不会死循环,但点击时对“已取出”的方法Count进行“裸引用”,按钮无反应。