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 相关文章推荐
javascript 匿名函数的理解(透彻版)
Jan 28 Javascript
jquery ajax的success回调函数中实现按钮置灰倒计时
Nov 19 Javascript
Jquery 动态循环输出表格具体方法
Nov 23 Javascript
写JQuery插件的基本知识
Nov 25 Javascript
Javascript编程之继承实例汇总
Nov 28 Javascript
Node.js 异步异常的处理与domain模块解析
May 10 Javascript
AngularJS实现自定义指令及指令配置项的方法
Nov 20 Javascript
vue和webpack打包项目相对路径修改的方法
Jun 15 Javascript
移动端吸顶fixbar的解决方案详解
Jul 17 Javascript
vue+node 实现视频在线播放的实例代码
Oct 19 Javascript
基于react项目打包css引用路径错误解决方案
Oct 28 Javascript
vue 使用vant插件做tabs切换和无限加载功能的实现
Nov 04 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和ACCESS写聊天室(七)
2006/10/09 PHP
关于mysql字符集设置了character_set_client=binary 在gbk情况下会出现表描述是乱码的情况
2013/01/06 PHP
php接口和抽象类使用示例详解
2014/03/02 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
2014/10/21 PHP
php使用function_exists判断函数可用的方法
2014/11/19 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
2015/12/10 PHP
php实现36进制与10进制转换功能示例
2017/01/10 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
2019/12/01 PHP
Extjs学习过程中新手容易碰到的低级错误积累
2010/02/11 Javascript
js操作checkbox遇到的问题解决
2013/06/29 Javascript
点击按钮或链接不跳转只刷新页面的脚本整理
2013/10/22 Javascript
javascript特殊用法示例介绍
2013/11/29 Javascript
jQuery创建DOM元素实例解析
2015/01/19 Javascript
jQuery添加删除DOM元素方法详解
2016/01/18 Javascript
分步解析JavaScript实现tab选项卡自动切换功能
2016/01/25 Javascript
基于vue实现多引擎搜索及关键字提示
2017/03/16 Javascript
深入理解ES6学习笔记之块级作用域绑定
2017/08/19 Javascript
Angular利用trackBy提升性能的方法
2018/01/26 Javascript
vue中v-for通过动态绑定class实现触发效果
2018/12/06 Javascript
浅谈vue项目利用Hbuilder打包成APP流程,以及遇到的坑
2020/09/12 Javascript
[49:56]VG vs Optic 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python最长公共子串算法实例
2015/03/07 Python
在Python中使用next()方法操作文件的教程
2015/05/24 Python
Python语言描述机器学习之Logistic回归算法
2017/12/21 Python
Python通过属性手段实现只允许调用一次的示例讲解
2018/04/21 Python
pytorch中torch.max和Tensor.view函数用法详解
2020/01/03 Python
评析教师个人的自我评价
2014/02/19 职场文书
没有孩子的离婚协议书怎么写
2014/09/17 职场文书
2015年检验员工作总结范文
2015/04/30 职场文书
社会主义核心价值观主题教育活动总结
2015/05/07 职场文书
入党函调证明材料
2015/06/19 职场文书
品牌形象定位,全面分析
2019/07/23 职场文书
【超详细】八大排序算法的各项比较以及各自特点
2021/03/31 Python
如何用JS实现网页瀑布流布局
2021/04/24 Javascript
golang实现一个简单的websocket聊天室功能
2021/10/05 Golang
mybatis 获取更新记录的id
2022/05/20 Java/Android