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 相关文章推荐
Enter回车切换输入焦点实现思路与代码兼容各大浏览器
Sep 01 Javascript
玩转JavaScript OOP - 类的实现详解
Jun 08 Javascript
jQuery插件zTree实现更新根节点中第i个节点名称的方法示例
Mar 08 Javascript
BootStrap selectpicker后台动态绑定数据
Jun 01 Javascript
微信小程序 input表单与redio及下拉列表的使用实例
Sep 20 Javascript
vue-router2.0 组件之间传参及获取动态参数的方法
Nov 10 Javascript
VueRouter导航守卫用法详解
Dec 25 Javascript
微信小程序checkbox组件使用详解
Jan 31 Javascript
详解Node.js读写中文内容文件操作
Oct 10 Javascript
Three.js实现3D机房效果
Dec 30 Javascript
Layui实现数据表格默认全部显示(不要分页)
Oct 26 Javascript
使用Vue.set()方法实现响应式修改数组数据步骤
Nov 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
PHP下对字符串的递增运算代码
2010/08/21 PHP
非常好用的Zend Framework分页类
2014/06/25 PHP
destoon实现调用热门关键字的方法
2014/07/15 PHP
学习php设计模式 php实现适配器模式
2015/12/07 PHP
php阿拉伯数字转中文人民币大写
2015/12/21 PHP
PHP正则获取页面所有图片地址
2016/03/23 PHP
PHP实现数组array转换成xml的方法
2016/07/19 PHP
PHP读取word文档的方法分析【基于COM组件】
2017/08/01 PHP
PHP+Session防止表单重复提交的解决方法
2018/04/09 PHP
Javascript对象中关于setTimeout和setInterval的this介绍
2012/07/21 Javascript
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
jQuery阻止同类型事件小结
2013/04/19 Javascript
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
浏览器图片选择预览、旋转、批量上传的JS代码实现
2013/12/04 Javascript
$(document).ready(function() {})不执行初始化脚本
2014/06/19 Javascript
jQuery中offset()方法用法实例
2015/01/16 Javascript
JavaScript通过字典进行字符串翻译转换的方法
2015/03/19 Javascript
JS+CSS实现表格高亮的方法
2015/08/05 Javascript
Js+Ajax,Get和Post在使用上的区别小结
2016/06/08 Javascript
js 定义对象数组(结合)多维数组方法
2016/07/27 Javascript
详解JavaScript添加给定的标签选项
2018/09/17 Javascript
vue强制刷新组件的方法示例
2019/02/28 Javascript
详解vue中使用transition和animation的实例代码
2020/12/12 Vue.js
[05:46]DOTA2英雄梦之声_第18期_陈
2014/06/20 DOTA
浅谈Python类里的__init__方法函数,Python类的构造函数
2016/12/10 Python
Flask数据库迁移简单介绍
2017/10/24 Python
python实现求两个字符串的最长公共子串方法
2018/07/20 Python
解决python3中的requests解析中文页面出现乱码问题
2019/04/19 Python
python+selenium爬取微博热搜存入Mysql的实现方法
2021/01/27 Python
HTML5之SVG 2D入门9—蒙板及mask元素介绍与应用
2013/01/30 HTML / CSS
Vision Directa智利眼镜网:框架眼镜、隐形眼镜和名牌太阳眼镜
2016/11/23 全球购物
澳大利亚儿童鞋在线:The Trybe
2019/07/16 全球购物
什么是托管函数?托管函数有什么用?
2014/06/15 面试题
软件测试题目
2013/02/27 面试题
2015年教导处教学工作总结
2015/07/22 职场文书
JavaScript 定时器详情
2021/11/11 Javascript