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
通用JS事件写法实现代码
Jan 07 Javascript
javascript下4个跨浏览器必备的函数
Mar 07 Javascript
jquery和css3实现的炫酷时尚的菜单导航
Sep 01 Javascript
基于jquery实现等比缩放图片
Dec 03 Javascript
javascript匀速动画和缓冲动画详解
Oct 20 Javascript
详解angularJS自定义指令间的相互交互
Jul 05 Javascript
vue2.0 keep-alive最佳实践
Jul 06 Javascript
JavaScript数组push方法使用注意事项
Oct 30 Javascript
vue移动端微信授权登录插件封装的实例
Aug 28 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
Apr 28 jQuery
vue3.0+vue-router+element-plus初实践
Dec 02 Vue.js
浅谈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 spl_autoload_register实现自动加载研究
2011/12/06 PHP
基于PHP开发中的安全防范知识详解
2013/06/06 PHP
PHP中Closure类的使用方法及详解
2015/10/09 PHP
PHP基于接口技术实现简单的多态应用完整实例
2017/04/26 PHP
PHP将英文数字转换为阿拉伯数字实例讲解
2019/01/28 PHP
用js实现键盘方向键翻页功能的代码
2007/06/03 Javascript
JQury slideToggle闪烁问题及解决办法
2011/07/05 Javascript
js简单实现让文本框内容逐个字的显示出来
2013/10/22 Javascript
jsonp原理及使用
2013/10/28 Javascript
JavaScript之数组(Array)详解
2015/04/01 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
Javascript中prototype的使用详解
2016/06/18 Javascript
基于vue.js实现图片轮播效果
2016/12/01 Javascript
完美解决node.js中使用https请求报CERT_UNTRUSTED的问题
2017/01/08 Javascript
Vue.use源码学习小结
2018/06/20 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
js实现贪吃蛇游戏(简易版)
2020/09/29 Javascript
vue+Element-ui前端实现分页效果
2020/11/15 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
利用python3随机生成中文字符的实现方法
2017/11/24 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
2018/01/04 Python
关于Python作用域自学总结
2019/06/10 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
Python实现不规则图形填充的思路
2020/02/02 Python
Django 解决阿里云部署同步数据库报错的问题
2020/05/14 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
2020/11/20 Python
Python批量修改xml的坐标值全部转为整数的实例代码
2020/11/26 Python
浅谈Html5多线程开发之WebWorkers
2018/05/02 HTML / CSS
英国顶尖手表珠宝品牌独家授权经销商:HS Johnson
2020/10/28 全球购物
七年级生物教学反思
2014/01/30 职场文书
翻译学院毕业生自荐书
2014/02/02 职场文书
数学系毕业生求职信
2014/05/29 职场文书
2015年防汛工作总结
2015/05/15 职场文书
借条如何写
2015/05/26 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
如何理解PHP核心特性命名空间
2021/05/28 PHP