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高级程序设计 读书笔记之十一 内置对象Global
Mar 07 Javascript
css3元素简单的闪烁效果实现(html5 jquery)
Dec 28 Javascript
JavaScript中实现异步编程模式的4种方法
Sep 24 Javascript
js中的json对象详细介绍
Oct 29 Javascript
jQuery元素的隐藏与显示实例
Jan 20 Javascript
JavaScript时间转换处理函数
Apr 14 Javascript
jquery使用iscorll实现上拉、下拉加载刷新
Oct 26 jQuery
JS/jQuery实现DIV延时几秒后消失或显示的方法
Feb 12 jQuery
解决bootstrap-select 动态加载数据不显示的问题
Aug 10 Javascript
详解js模板引擎art template数组渲染的方法
Oct 09 Javascript
JavaScript在web自动化测试中的作用示例详解
Aug 25 Javascript
vue-admin-template配置快捷导航的代码(标签导航栏)
Sep 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函数,php爱好者站推荐
2007/03/19 PHP
thinkPHP3.1验证码的简单实现方法
2016/04/22 PHP
laravel利用中间件防止未登录用户直接访问后台的方法
2019/09/30 PHP
PHP xpath提取网页数据内容代码解析
2020/07/16 PHP
css3实现背景模糊的三种方式
2021/03/09 HTML / CSS
ASP.NET jQuery 实例3 (在TextBox里面阻止复制、剪切和粘贴事件)
2012/01/13 Javascript
Javascript 面向对象(二)封装代码
2012/05/23 Javascript
BootStrap glyphicons 字体图标实现方法
2016/05/01 Javascript
BootStrap Typeahead自动补全插件实例代码
2016/08/10 Javascript
JS简单去除数组中重复项的方法
2016/09/13 Javascript
Node.js 实现简单小说爬虫实例
2016/11/18 Javascript
JavaScript实现带有子菜单和控件的slider轮播图效果
2017/11/01 Javascript
angular2路由之routerLinkActive指令【推荐】
2018/05/30 Javascript
Vue使用vue-area-linkage实现地址三级联动效果的示例
2018/06/27 Javascript
vue + typescript + video.js实现 流媒体播放 视频监控功能
2019/07/07 Javascript
小程序实现悬浮搜索框
2019/07/12 Javascript
解决layui-table单元格设置为百分比在ie8下不能自适应的问题
2019/09/28 Javascript
vuex存值与取值的实例
2019/11/06 Javascript
Vue 路由间跳转和新开窗口的方式(query、params)
2019/12/25 Javascript
vue实现标签云效果的示例
2020/11/09 Javascript
[03:58]兄弟们,回来开黑了!DOTA2昔日战友招募宣传视频
2016/07/17 DOTA
[03:55]TI9战队采访——TNC Predator
2019/08/22 DOTA
[08:38]DOTA2-DPC中国联赛 正赛 VG vs Elephant 选手采访
2021/03/11 DOTA
Python使用urllib模块的urlopen超时问题解决方法
2014/11/08 Python
Python打包文件夹的方法小结(zip,tar,tar.gz等)
2016/09/18 Python
Python2包含中文报错的解决方法
2018/07/09 Python
python利用selenium进行浏览器爬虫
2019/04/25 Python
TensorFlow 输出checkpoint 中的变量名与变量值方式
2020/02/11 Python
Python matplotlib图例放在外侧保存时显示不完整问题解决
2020/07/28 Python
详解使用python爬取抖音app视频(appium可以操控手机)
2021/01/26 Python
使用css创建三角形 使用CSS3创建3d四面体原理及代码(html5实践)
2013/01/06 HTML / CSS
很酷的小工具和电子产品商城:GearBest
2016/11/19 全球购物
党员群众路线对照检查材料思想汇报
2014/09/17 职场文书
试用期辞职信范文
2015/03/02 职场文书
推广普通话主题班会
2015/08/17 职场文书
虚拟机linux端mysql数据库无法远程访问的解决办法
2021/05/26 MySQL