react 的事件处理会丢失 this, 所以需要绑定, 为什么会丢失 this?
首先来看摘自官方的一句话:
You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default.
这句话大概意思就是, 你要小心 jax 回调函数里面的 this,class 方法默认是不会绑定它的
第一种, 在 constructor 里面用 bind 绑定 this
- 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>
- );
- }
这个时候我想起了原生 dom 绑定 click 的方法
<button onclick ="handleClick()">点我</button>
两者比较, 我发现了个区别, 原生的绑定方法事件名后面多了个()
于是我尝试着在 react 里面的事件加一个()
- render() {
- return (
- <button onClick={ this.handleClick() }>
- {this.state.isToggleOn ? 'ON' : 'OFF'}
- </button>
- );
- }
就像上面这样, 然后我发现, 无论我怎么点, 都不会触发这个方法了, 再细心点, 就发现, 在渲染的时候, 就调用了一次, 而且仅此一次, 再也不能调用了.
原因是 jsx 语法, 渲染的时候会把 {} 里面包裹的代码先解析一遍, 因为如果加了括号, 直接就执行了里面的函数, 就没有东西了, 但是这个时候, this 是可以拿到的
- class App extends Component {
- handleClick(){
- console.log(this); // 下面调用加了(), 这个时候发现, this 是可以拿到的
- }
- render() {
- return (
- <div className="App">
- <button onClick={this.handleClick()}>点我</button> // 这里加了括号的
- </div>
- );
- }
- }
好像问题越来越明朗了, 为啥会拿不到, 和 class 没有关系, 完全是因为 react 自己封装的东西, 先会把 {} 里面的代码解析一遍, 于是大概就是下面这种情况了
- const obj = {
- num:1
- }
- obj.handleClick = function () {
- console.log(this);
- }
- console.log(eval(obj.handleClick )); // f(){ console.log(this) } react 对 {} 的解析
- (eval(obj.handleClick))() //onclick 触发点击事件 这里输出 this 是 Windows, 所以就等于丢失了 this 指向
- console.log(eval(() => { obj.handleClick() })); // () => { obj.handleClick() } react 对 {} 的解析
- (eval(() => {obj.handleClick()}))() //onclick 触发点击事件 这里输出 this 还是 obj, 所以 this 就保留了
所以问题出在 react 对 {} 的解析会把 this 的指向解除了
本文来自 React 答疑 https://www.html.cn/qa/react/ 栏目, 欢迎学习!
来源: http://www.css88.com/qa/react/14369.html