React组件中的this的具体使用


Posted in Javascript onFebruary 28, 2018

React组件的this是什么

通过编写一个简单组件,并渲染出来,分别打印出自定义函数和render中的this:

import React from 'react';

const STR = '被调用,this指向:';

class App extends React.Component{
  constructor(){
    super()
  }

  //测试函数
  handler() {
    console.log(`handler ${STR}`,this);
  }

  render(){

    console.log(`render ${STR}`,this);
    return(
      <div>
        <h1>hello World</h1>
        <label htmlFor = 'btn'>单击打印函数handler中this的指向</label>
        <input id = "btn" type="button" value = '单击' onClick = {this.handler}/>
      </div>    
    )
  }
}
export default App

结果如图:

React组件中的this的具体使用

可以看到,render函数中的this指向了组件实例,而handler()函数中的this则为undefined,这是为何?

JavaScript函数中的this

我们都知道JavaScript函数中的this不是在函数声明的时候定义的,而是在函数调用(即运行)的时候定义的

var student = {
  func: function() {
    console.log(this);
  };
};

student.func();
var studentFunc = student.func;
studentFunc();

这段代码运行,可以看到student.func()打印了student对象,因为此时this指向student对象;而studentFunc()打印了window,因为此时由window调用的,this指向window。

这段代码形象的验证了,JavaScript函数中的this不是在函数声明的时候,而是在函数运行的时候定义的;

同样,React组件也遵循JavaScript的这种特性,所以组件方法的‘调用者'不同会导致this的不同(这里的 “调用者” 指的是函数执行时的当前对象)

“调用者”不同导致this不同

测试:分别在组件自带的生命周期函数以及自定义函数中打印this,并在render()方法中分别使用this.handler(),window.handler(),onCilck={this.handler}这三种方法调用handler():

/App.jsx
//测试函数
  handler() {
    console.log(`handler ${STR}`,this);
  }

  render(){
    console.log(`render ${STR}`,this);

    this.handler();
    window.handler = this.handler;
    window.handler();

    return(

      <div>
        <h1>hello World</h1>
        <label htmlFor = 'btn'>单击打印函数handler中this的指向</label>
        <input id = "btn" type="button" value = '单击' onClick = {this.handler}/>
      </div>    
    )
  }
}
export default App

React组件中的this的具体使用

可以看到:

  1. render中this -> 组件实例App对象;
  2. render中this.handler() -> 组件实例App对象 ;
  3. render中window.handler() -> window对象;
  4. onClick ={this.handler} -> undefined

继续使用事件触发组件的装载、更新和卸载过程:

/index.js
import React from 'react'
import {render,unmountComponentAtNode} from 'react-dom'

import App from './App.jsx'


const root=document.getElementById('root')

console.log("首次挂载");
let instance = render(<App />,root);

window.renderComponent = () => {
  console.log("挂载");
  instance = render(<App />,root);
}

window.setState = () => {
  console.log("更新");
  instance.setState({foo: 'bar'});
}


window.unmountComponentAtNode = () => {
  console.log('卸载');
  unmountComponentAtNode(root);
}

使用三个按钮触发组件的装载、更新和卸载过程:

/index.html
<!DOCTYPE html>
<html>
<head>
  <title>react-this</title>
</head>
<body>
  <button onclick="window.renderComponent()">挂载</button>
  <button onclick="window.setState()">更新</button>
  <button onclick="window.unmountComponentAtNode()">卸载</button>
  <div id="root">
    <!-- app -->
  </div>
</body>
</html>

运行程序,依次单击“挂载”,绑定onClick={this.handler}“单击”按钮,“更新”和“卸载”按钮结果如下:

React组件中的this的具体使用

1. render()以及componentDIdMount()、componentDIdUpdate()等其他生命周期函数中的this都是组件实例;

2. this.handler()的调用者,为render()中的this,所以打印组件实例;

3. window.handler()的“调用者”,为window,所以打印window;

4. onClick={this.handler}的“调用者”为事件绑定,来源多样,这里打印undefined。

-面对如此混乱的场景,如果我们想在onClick中调用自定义的组件方法,并在该方法中获取组将实例,我们就得进行转换上下文即绑定上下文:

自动绑定和手动绑定

  1. React.createClass有一个内置的魔法,可以自动绑定所用的方法,使得其this指向组件的实例化对象,但是其他JavaScript类并没有这种特性;
  2. 所以React团队决定不再React组件类中实现自动绑定,把上下文转换的自由权交给开发者;
  3. 所以我们通常在构造函数中绑定方法的this指向:
import React from 'react';
const STR = '被调用,this指向:';
class App extends React.Component{
  constructor(){
    super();
    this.handler = this.handler.bind(this);
  }
//测试函数
  handler() {
    console.log(`handler ${STR}`,this);
  }

  render(){
    console.log(`render ${STR}`,this);
    this.handler();
    window.handler = this.handler;
    window.handler();

    return(
      <div>
        <h1>hello World</h1>
        <label htmlFor = 'btn'>单击打印函数handler中this的指向</label>
        <input id = "btn" type="button" value = '单击' onClick = {this.handler}/>
      </div>    
    )
  }
}
export default App

将this.handler()绑定为组件实例后,this.handler()中的this就指向组将实例,即onClick={this.handler}打印出来的为组件实例;

总结:

React组件生命周期函数中的this指向组件实例;

自定义组件方法的this会因调用者不同而不同;

为了在组件的自定义方法中获取组件实例,需要手动绑定this到组将实例。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
图片上传判断及预览脚本的效果实例
Aug 07 Javascript
用JavaScript计算在UTF-8下存储字符串占用字节数
Aug 08 Javascript
javascript date格式化示例
Sep 25 Javascript
js 判断一组日期是否是连续的简单实例
Jul 11 Javascript
简单实现js浮动框
Dec 13 Javascript
AngularJs的UI组件ui-Bootstrap之Tooltip和Popover
Jul 13 Javascript
在微信小程序里使用watch和computed的方法
Aug 02 Javascript
手把手教你写一个微信小程序(推荐)
Oct 17 Javascript
js作用域和作用域链及预解析
Apr 11 Javascript
vue.js实现左边导航切换右边内容
Oct 21 Javascript
jQuery实现颜色打字机的完整代码
Mar 19 jQuery
JavaScript如何实现监听键盘输入和鼠标监点击
Jul 20 Javascript
浅谈Vue网络请求之interceptors实际应用
Feb 28 #Javascript
Node.js中DNS模块学习总结
Feb 28 #Javascript
Vue自定义指令实现checkbox全选功能的方法
Feb 28 #Javascript
如何在vue中使用ts的示例代码
Feb 28 #Javascript
angularjs select 赋值 ng-options配置方法
Feb 28 #Javascript
select获取下拉框的值 下拉框默认选中方法
Feb 28 #Javascript
AngularJS select加载数据选中默认值的方法
Feb 28 #Javascript
You might like
9个经典的PHP代码片段分享
2014/12/18 PHP
大家须知简单的php性能优化注意点
2016/01/04 PHP
Laravel下生成验证码的类
2017/11/15 PHP
PHP中数组转换为SimpleXML教程
2019/01/27 PHP
laravel利用中间件防止未登录用户直接访问后台的方法
2019/09/30 PHP
深入认识JavaScript中的函数
2007/01/22 Javascript
在IE6下发生Internet Explorer cannot open the Internet site错误
2010/06/21 Javascript
jquery validate使用攻略 第四步
2010/07/01 Javascript
window.dialogArguments 使用说明
2011/04/11 Javascript
jquery随机展示头像代码
2011/12/21 Javascript
js中数组(Array)的排序(sort)注意事项说明
2014/01/24 Javascript
node.js中的path.isAbsolute方法使用说明
2014/12/08 Javascript
JavaScript中Boolean对象的属性解析
2015/10/21 Javascript
JavaScript匿名函数之模仿块级作用域
2015/12/12 Javascript
JavaScript核心语法总结(推荐)
2016/06/02 Javascript
JavaScript数组的定义及数字操作技巧
2016/06/06 Javascript
AngularJS中的Promise详细介绍及实例代码
2016/12/13 Javascript
JS打开摄像头并截图上传示例
2017/02/18 Javascript
JS设计模式之访问者模式定义与用法分析
2018/02/05 Javascript
解决vue处理axios post请求传参的问题
2018/03/05 Javascript
vue左右侧联动滚动的实现代码
2018/06/06 Javascript
js动态设置select下拉菜单的默认选中项实例
2018/08/21 Javascript
深入理解与使用keep-alive(配合router-view缓存整个路由页面)
2018/09/25 Javascript
JavaScript对象原型链原理详解
2020/02/05 Javascript
Python合并同一个文件夹下所有PDF文件的方法
2019/03/11 Python
python 按钮点击关闭窗口的实现
2020/03/04 Python
python邮件中附加文字、html、图片、附件实现方法
2021/01/04 Python
使用CSS3设计地图上的雷达定位提示效果
2016/04/05 HTML / CSS
美国二手奢侈品寄售网站:TheRealReal
2016/10/29 全球购物
Merrell迈乐澳大利亚网站:购买户外登山鞋
2017/05/28 全球购物
Beauty Expert美国/加拿大:购买奢侈美容产品
2018/12/05 全球购物
波兰最大的电商平台:Allegro.pl
2021/02/06 全球购物
小学生期末自我鉴定
2014/01/19 职场文书
户外亲子活动策划方案
2014/02/07 职场文书
四查四看剖析材料
2014/02/14 职场文书
高温慰问简报
2015/07/21 职场文书