Vue 中this

579 阅读3分钟

在 Vue 中,this 通常指向当前组件的实例,可以通过 this 访问组件的属性、方法、计算属性等。

一般来说,以下情况 this 指向 Vue 实例本身:

  • 所有的生命周期函数(如 createdmountedupdated 以及 destroyed等)中的 this 都指向调用它的 Vue 实例。

  • methods 中的普通函数(非箭头函数)的 this 指向 Vue 实例。

然而,在一些情况下,this 的指向可能会有所不同:

  • data 中的 this 指向 window

  • Vue 的 v-on 指令中接收的 JavaScript 语句中的 this 是 window(但在 Vue 组件中的 v-on 指令除外)。

  • methods 中箭头函数没有自己的 this,其 this 指向其宿主对象的 this。如果宿主对象是普通函数,那么需要具体分析该普通函数被调用时的 this 指向;如果宿主对象是 Vue 实例,那么箭头函数中的 this 通常指向 Vue 实例。

  • 普通函数形式的回调函数(如定时器的回调、Ajax 的回调等)的 this 是 window,箭头函数形式的回调函数的 this 遵循箭头函数的原则(大多数情况下是 Vue 实例对象)。

例如:

export default {
  data() {
    return {
      message: "你好!"
    };
  },
  created() {
    console.log(this); // 在所有生命周期钩子方法里使用 this,指向使用它的 Vue 实例
  },
  methods: {
    showMessage3() {
      console.log(this); // Vue 实例调用了 showMessage3 方法,this 自然指向 Vue 实例
    },
    showMessage1() {
      setTimeout(function() {
        console.log(this); // 指向 window,因为没人调用这个普通函数
      }, 10);
    },
    showMessage2() {
      setTimeout(() => {
        console.log(this); // this 指向 Vue 实例
      }, 10);
    }
  }
}

如果在某些情况下无法直接获取到正确的 this,可以使用以下方法来解决:

  1. 使用 bind 方法:对回调函数中的匿名函数使用 bind(this) 绑定到 Vue 实例的 this。例如将 showMessage1 方法修改为:

showMessage1() {
  setTimeout(function() {
    console.log(this); // 现在指向 Vue 实例
  }.bind(this), 10);
}
  1. 把 Vue 实例的 this 赋值给另一个变量再使用:

showMessage1() {
  const self = this;
  setTimeout(function() {
    console.log(self); // 指向 Vue 实例
  }, 10);
}

在 Vue 3 中,setup 函数中的 this 指向有所变化。在 setup 函数内部,this 不会是该活跃实例的引用(即不指向 Vue 实例),因为 setup 是在解析其它组件选项之前被调用的,所以 setup 内部的 this 的行为与其它选项中的 this 完全不同。为了在 Vue 3 的 setup 函数或生命周期函数中使用 this,可以使用 getCurrentInstance 方法,该方法返回了 ctx 和 proxy,通过它们可以完成在 Vue 2 中 this 的使用场景。示例如下:

<script setup>
import { getCurrentInstance } from '@vue/runtime-core';
const currentInstance = ref();
onMounted(() => {
  currentInstance.value = getCurrentInstance();
});
</script>

需注意,不要在 Vue 3 的方法中使用 getCurrentInstance 来获取 this,它只在 setup、生命周期函数中有效。另外,为了避免 this 指向出现问题,通常在回调函数中会使用箭头函数或者通过绑定 this 来确保 this 的指向。遵循最佳实践,避免在模板中直接使用 this,可定义一个计算属性或方法来公开所需的组件状态,在 methods 中尽量使用普通函数而非箭头函数来定义方法。