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 相关文章推荐
Z-Blog中用到的js代码
Mar 15 Javascript
javascript 获取表单file全路径
Dec 31 Javascript
理解JSON:3分钟课程
Oct 28 Javascript
Extjs NumberField后面加单位实现思路
Jul 30 Javascript
JS实现点击按钮后框架内载入不同网页的方法
May 05 Javascript
javascript实现跨域的方法汇总
Jun 25 Javascript
js实现iframe框架取值的方法(兼容IE,firefox,chrome等)
Nov 26 Javascript
javascript回到顶部特效
Jul 30 Javascript
JavaScript实现类似拉勾网的鼠标移入移出效果
Oct 27 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
Jul 14 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
Apr 23 Javascript
vue 实现滚动到底部翻页效果(pc端)
Jul 31 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入门小知识
2008/03/24 PHP
phplot生成图片类用法详解
2015/01/06 PHP
PHP开发中解决并发问题的几种实现方法分析
2017/11/13 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
jquery插件冲突(jquery.noconflict)解决方法分享
2014/03/20 Javascript
js实现当前输入框高亮显示的方法
2015/08/19 Javascript
js淡入淡出的图片轮播效果代码分享
2015/08/24 Javascript
javascript下拉列表中显示树形菜单的实现方法
2015/11/17 Javascript
jQuery EasyUI 入门必看
2016/06/03 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
2016/07/12 Javascript
JavaScript登录验证码的实现
2016/10/27 Javascript
Node.js复制文件的方法示例
2016/12/29 Javascript
js 博客内容进度插件详解
2017/02/19 Javascript
使用gulp搭建本地服务器并实现模拟ajax
2017/04/05 Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
2017/06/04 Javascript
Vue 组件(component)教程之实现精美的日历方法示例
2018/01/08 Javascript
微信小程序仿知乎实现评论留言功能
2018/11/28 Javascript
基于vue框架手写一个notify插件实现通知功能的方法
2019/03/31 Javascript
JS实现的字符串数组去重功能小结
2019/06/17 Javascript
vue 清空input标签 中file的值操作
2020/07/21 Javascript
vue 弹出遮罩层样式实例
2020/07/22 Javascript
PIL包中Image模块的convert()函数的具体使用
2020/02/26 Python
Python改变对象的字符串显示的方法
2020/08/01 Python
Python爬虫+tkinter界面实现历史天气查询的思路详解
2021/02/22 Python
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
平面设计师工作职责范文
2013/12/03 职场文书
物理教学随笔感言
2014/02/22 职场文书
5.12护士节演讲稿
2014/04/30 职场文书
体育教育毕业生自荐信
2014/06/29 职场文书
会议通知格式范文
2015/04/15 职场文书
中学音乐课教学反思
2016/02/18 职场文书
2019辞职报告范本3篇!
2019/07/23 职场文书
读《推着妈妈去旅行》有感1500字
2019/10/15 职场文书
Golang 空map和未初始化map的注意事项说明
2021/04/29 Golang
动画《新网球王子 U-17 WORLD CUP》希腊队PV公开
2022/04/02 日漫