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 相关文章推荐
JS启动应用程序的一个简单例子
May 11 Javascript
js获取元素在浏览器中的绝对位置
Jul 24 Javascript
javascript 弹出窗口中是否显示地址栏的实现代码
Apr 14 Javascript
一些实用的jQuery代码片段收集
Jul 12 Javascript
基于OO的动画附加插件,可以实现弹跳、渐隐等动画效果 分享
Jun 24 Javascript
javascript结合fileReader 实现上传图片
Jan 30 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
Oct 08 Javascript
JS仿JQuery选择器功能
Mar 08 Javascript
微信小程序 弹窗自定义实例代码
Mar 08 Javascript
jQuery设置图片等比例缩小的方法
Apr 29 jQuery
基于pako.js实现gzip的压缩和解压功能示例
Jun 13 Javascript
js实现3D旋转效果
Aug 18 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
利用discuz自带通行证整合dedecms的方法以及文件下载
2007/03/06 PHP
PHP版微信公众平台红包API
2015/04/02 PHP
B/S开发中常用javaScript技术与代码
2007/03/09 Javascript
JQuery跨Iframe选择实现代码
2010/08/19 Javascript
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
jquery Mobile入门—外部链接切换示例代码
2013/01/08 Javascript
动态显示可输入的字数提示还可以输入的字数
2014/04/01 Javascript
js判断变量初始化的三种形式及推荐用的形式
2014/07/22 Javascript
浅谈JavaScript中定义变量时有无var声明的区别
2014/08/18 Javascript
实现图片预加载的三大方法及优缺点分析
2014/11/19 Javascript
jQuery插件ajaxFileUpload使用实例解析
2016/10/19 Javascript
JQuery获取鼠标进入和离开容器的方向
2016/12/29 Javascript
最常见和最有用的字符串相关的方法详解
2017/02/06 Javascript
微信小程序基于本地缓存实现点赞功能的方法
2017/12/18 Javascript
vue设置导航栏、侧边栏为公共页面的例子
2019/11/01 Javascript
[00:43]TI7不朽珍藏III——幽鬼不朽展示
2017/07/15 DOTA
[46:50]Liquid vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
[01:01:18]VP vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python中摘要算法MD5,SHA1简介及应用实例代码
2018/01/09 Python
浅谈pandas中DataFrame关于显示值省略的解决方法
2018/04/08 Python
基于DataFrame筛选数据与loc的用法详解
2018/05/18 Python
Django 过滤器汇总及自定义过滤器使用详解
2019/07/19 Python
基于python cut和qcut的用法及区别详解
2019/11/22 Python
Python通过两个dataframe用for循环求笛卡尔积
2020/04/29 Python
Python面向对象特殊属性及方法解析
2020/09/16 Python
python cookie反爬处理的实现
2020/11/01 Python
C++面试题目
2013/06/25 面试题
应届毕业生自我鉴定范文
2013/12/27 职场文书
迅雷Cued工作心得体会
2014/01/27 职场文书
办公自动化毕业生求职信
2014/03/09 职场文书
学雷锋标兵事迹材料
2014/08/18 职场文书
地震捐款倡议书
2014/08/29 职场文书
详细的本科生职业生涯规划范文
2014/09/16 职场文书
Python 批量下载阴阳师网站壁纸
2021/05/19 Python
详解解Django 多对多表关系的三种创建方式
2021/08/23 Python
nginx中封禁ip和允许内网ip访问的实现示例
2022/03/17 Servers