回调函数的this指向

毕设的前端 Vue 项目中遇到一个问题:

在登录方法中使用 axios 进行数据交互之后,回调函数中使用 this.$notify()提示“该组件未注册”,也就是说 this 绑定的对象因为回调函数改变了指向。

// 有问题的写法
methods: {
  login: function(){
    axios.post('/api/admin/login', postData).then( function(response){
      // 注意这里的写法,使用匿名函数
            if (response.data === 1) {
              this.$notify.info("登录成功") // 这句提示notify组件未注册。
            } else {
              this.$notify.error("用户名或密码错误!") // 这句同理
            }
          }).catch(function (error) {
            console.log(error);
          });
  }
}

ES5 规范中,this 指向当前活动对象,在回调函数执行的时候,this 从当前 app 实例(Vue 组件创建的全局变量 app)指向了回调函数执行者,$notify 不是 axios 方法,因此会产生未注册错误。

但是 ES6 写法就会避免这个问题,箭头函数回调之后,this 仍指向当前活动对象。

// 正确写法
methods: {
  login: function(){
    axios.post('/api/admin/login', postData).then((response) => {
      // 注意这里,改为箭头函数
            if (response.data === 1) {
              this.$notify.info("登录成功") // 此处正常工作
            } else {
              this.$notify.error("用户名或密码错误!") // 这句同理
            }
          }).catch(function (error) {
            console.log(error);
          });
  }
}

这两组代码的差别在于:请求成功后的回调函数,一个使用匿名函数,一个使用箭头函数

  • 匿名函数的指针指向->函数操作的本身
  • 箭头函数的指针指向->组件

也就是说当你需要使用到组件中声明的变量或者函数,就需要使用箭头函数

另外,使用 ES5 标准时可以将 this 的指向保存下来

// ES5替代写法
methods: {
  login: function(){
    let current = this;
    axios.post('/api/admin/login', postData).then( function(response){
      // 匿名函数
            if (response.data === 1) {
              current.$notify.info("登录成功") // 此处正常工作,因为current就是回调外的this
            } else {
              current.$notify.error("用户名或密码错误!") // 同理
            }
          }).catch(function (error) {
            console.log(error);
          });
  }
}