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 相关文章推荐
IE浏览器打印的页眉页脚设置解决方法
Dec 08 Javascript
jValidate 基于jQuery的表单验证插件
Dec 12 Javascript
基于jquery中children()与find()的区别介绍
Apr 26 Javascript
Sortable.js拖拽排序使用方法解析
Nov 04 Javascript
JQueryEasyUI框架下的combobox的取值和绑定的方法
Jan 22 Javascript
js 作用域和变量详解
Feb 16 Javascript
详解在HTTPS 项目中使用百度地图 API
Apr 26 Javascript
layui 实现加载动画以及非真实加载进度的方法
Sep 23 Javascript
Vue混入mixins滚动触底的方法
Nov 22 Javascript
分享几个JavaScript运算符的使用技巧
Apr 24 Javascript
vue中div禁止点击事件的实现
Apr 02 Vue.js
Java无向树分析 实现最小高度树
Apr 09 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
ioncube_loader_win_5.2.dll的错误解决方法
2015/01/04 PHP
PHP、Java des加密解密实例
2015/04/27 PHP
基于PHP实现通过照片获取ip地址
2016/04/26 PHP
PHP入门教程之图像处理技巧分析
2016/09/11 PHP
yii2 url重写并隐藏index.php方法
2018/12/10 PHP
JTrackBar水平拖动效果
2007/07/15 Javascript
来自国外的30个基于jquery的Web下拉菜单
2012/06/22 Javascript
Javascript中查找不以XX字符结尾的单词示例代码
2013/10/15 Javascript
js捕获鼠标滚轮事件代码
2013/12/16 Javascript
JQuery判断HTML元素是否存在的两种解决方法
2013/12/26 Javascript
JS是按值传递还是按引用传递
2015/01/30 Javascript
jQuery使用正则表达式限制文本框只能输入数字
2016/06/18 Javascript
高效Web开发的10个jQuery代码片段
2016/07/22 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
2016/10/04 Javascript
JavaScript SHA512加密算法详细代码
2016/10/06 Javascript
JavaScript中Array对象用法实例总结
2016/11/29 Javascript
javascript中BOM基础知识总结
2017/02/14 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
js解决软键盘遮挡输入框的问题分享
2017/12/19 Javascript
微信小程序实现页面浮动导航
2019/01/28 Javascript
一文读懂ES7中的javascript修饰器
2019/05/06 Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
2020/04/26 Javascript
简单介绍Python中用于求最小值的min()方法
2015/05/15 Python
Python抓取聚划算商品分析页面获取商品信息并以XML格式保存到本地
2018/02/23 Python
TensorFlow模型保存/载入的两种方法
2018/03/08 Python
Python3 Post登录并且保存cookie登录其他页面的方法
2018/12/28 Python
PyQt5 加载图片和文本文件的实例
2019/06/14 Python
Python facenet进行人脸识别测试过程解析
2019/08/16 Python
Python计算IV值的示例讲解
2020/02/28 Python
Python生成器generator原理及用法解析
2020/07/20 Python
Pytest单元测试框架如何实现参数化
2020/09/05 Python
通俗易懂了解Python装饰器原理
2020/09/17 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
公司董事长职责
2013/12/12 职场文书
幼儿教师考核制度
2014/01/25 职场文书
Vue3 Composition API的使用简介
2021/03/29 Vue.js