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+html+css实现鼠标移动div实例
Jan 30 Javascript
从数据库读取数据后将其输出成html标签的三种方法
Oct 13 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
Oct 17 Javascript
Jquery easyui 实现动态树
Nov 17 Javascript
Javascript中的迭代、归并方法详解
Jun 14 Javascript
基于JS实现移动端向左滑动出现删除按钮功能
Feb 22 Javascript
JS闭包用法实例分析
Mar 27 Javascript
canvas+gif.js打造自己的数字雨头像的示例代码
Oct 26 Javascript
js保留两位小数方法总结
Jan 31 Javascript
layui清空,重置表单数据的实例
Sep 12 Javascript
jQuery 移除事件的方法
Jun 20 jQuery
vue项目接口管理,所有接口都在apis文件夹中统一管理操作
Aug 13 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
PHP学习笔记之二
2011/01/17 PHP
解析php中用PHPMailer来发送邮件的示例(126.com的例子)
2013/06/24 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
2014/08/08 PHP
php常用的安全过滤函数集锦
2014/10/09 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
2014/10/21 PHP
朋友网关于QQ相关的PHP代码(研究QQ的绝佳资料)
2015/01/26 PHP
php实现window平台的checkdnsrr函数
2015/05/27 PHP
PHP实现的简单网络硬盘
2015/07/29 PHP
Extjs显示从数据库取出时间转换JSON后的出现问题
2012/11/20 Javascript
js+css实现增加表单可用性之提示文字
2013/06/03 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
JavaScript数据结构与算法之链表
2016/01/29 Javascript
JS实用技巧小结(屏蔽错误、div滚动条设置、背景图片位置等)
2016/06/16 Javascript
jQuery插件简单学习实例教程
2016/07/01 Javascript
js防阻塞加载的实现方法
2016/09/09 Javascript
Javascript 动态改变imput type属性
2016/11/01 Javascript
微信小程序录音与播放录音功能
2017/12/25 Javascript
微信小程序中使用ECharts 异步加载数据的方法
2018/06/27 Javascript
JQuery 实现文件下载的常用方法分析
2019/10/29 jQuery
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
通过实例解析chrome如何在mac环境中安装vue-devtools插件
2020/07/10 Javascript
axios封装与传参示例详解
2020/10/18 Javascript
[04:16]DOTA2英雄梦之声_第09期_斧王
2014/06/21 DOTA
Python实现CET查分的方法
2015/03/10 Python
python opencv旋转图像(保持图像不被裁减)
2018/07/26 Python
python爬虫 urllib模块url编码处理详解
2019/08/20 Python
中国综合性网上购物商城:当当(网上卖书起家)
2016/11/16 全球购物
PHP引擎php.ini参数优化深入讲解
2021/03/24 PHP
高校学生干部的自我评价分享
2013/11/04 职场文书
《再别康桥》教学反思
2014/02/12 职场文书
高一新生军训方案
2014/05/12 职场文书
环境科学专业教师求职信
2014/07/12 职场文书
毛主席纪念堂观后感
2015/06/17 职场文书
换届选举主持词
2015/07/03 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书