解决前端开发过程中this绑定丢失的问题

问题提出

在前端开发过程中,如果函数嵌套过多,非常容易出现this的上下文隐式丢失的问题。例如下面的代码,代码中的html部分请见附录。

<script>
  export default {
    name: "listapp",
    data() {
      return {
        studentList: []
      };
    },
    mounted: function() {
       this.$axios
        .get("../json/StudentList.json")
        .then(function(resp) {
          this.studentList = resp.data.students;
        }); 
    }
  };
</script>

上面的代码在前端基于Vue的项目开发过程中非常常见,我们通常用axios进行异步方法调用,以获取服务器端数据。然后在Promise的then方法中,把获取到的数据渲染到页面上。

在数据渲染过程中,我们会发现在then方法中,this不再指向当前Vue对象。所以很遗憾,这段代码执行后,是不能把学生信息显示到表格里面的。

因为在then的匿名回调函数中,this并不能指向Vue对象,也就无法对界面进行渲染。
this.studentList = resp.data.students;

解决方法

针对上述问题,我提出了三种解决方案。

  1. 词法作用域法,在this上下文绑定丢失前,进行备份。在then方法中通过使用备份this,进行页面渲染。代码如下:
 mounted: function() {
 	   let self = this; //在this绑定丢失前,备份this
       this.$axios
        .get("../json/StudentList.json")
        .then(function(resp) {
          self.studentList = resp.data.students;
          /* seft */
        }); 
    }
  1. 基于ES5的bind方法,将回调方法中的this强制绑定到当前Vue对象。代码如下:
mounted: function() {
      this.$axios
       .get("../json/StudentList.json")
       .then(function(resp) {
         this.studentList = resp.data.students;
       }.bind(this));  // bind方法可以生成新的回调函数,将该函数绑定当前Vue对象。
   }
  1. 基于ES6的解决方法有两个,首先是箭头函数,其次是async/await。

    箭头函数的this指向是函数被创建时绑定的,它的指向就是当前词法作用域中的this,与调用方式无关,this不会因为调用者而改变。也就不存在this绑定的隐式消失问题。代码如下:

 mounted: function() {
       this.$axios
        .get("../json/StudentList.json")
        .then(resp => {
          this.studentList = resp.data.students;
        }); 
    }

async/await是ES6中新的异步处理方式,无需再使用回调函数,也就不存在函数嵌套,也就没有this绑定的隐式消失问题。

 mounted: async function() {
       let resp =  this.$axios.get("../json/StudentList.json");
       this.studentList = resp.data.students;
    }

分析

this绑定的隐式消失问题,存在于ES5及之前的Javascript版本中,在ES6中彻底得到解决。因此个人觉得在复杂的前端逻辑中,基于ES6的解决方式更加简单易用,同时也更符合前端的开发潮流。当然,如果需要兼容低版本的浏览器,前两个解决方案也可以在项目中使用。

附录

示例程序中的html部分:

<template>
  <div class="container">
    <table>
    	<thead>
    		<tr>
    			<th>StudentNo</th>
    			<th>Name</th>
    			<th>Address</th>
    		</tr>
    	</thead>
    	<tbody>
    		<tr v-for="item in studentList">
    			<td>{{item.Id}}</td>
    			<td>{{item.Name}}</td>
    			<td>{{item.Name}}</td>
    		</tr>
    	</body>
    </table>
  </div>
</template>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值