在 Vue 中,this 通常指向当前组件的实例,可以通过 this 访问组件的属性、方法、计算属性等。
一般来说,以下情况 this 指向 Vue 实例本身:
-
所有的生命周期函数(如
created、mounted、updated以及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,可以使用以下方法来解决:
-
使用
bind方法:对回调函数中的匿名函数使用bind(this)绑定到 Vue 实例的this。例如将showMessage1方法修改为:
showMessage1() {
setTimeout(function() {
console.log(this); // 现在指向 Vue 实例
}.bind(this), 10);
}
-
把 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 中尽量使用普通函数而非箭头函数来定义方法。