一文搞懂 vue3 中获取 app 实例、组件实例的方法
一、vue2.0
1、main.js 中
import api from './api' // 导入api接口
Vue.prototype.$api = api
Vue.prototype.$abc = 111
2、.vue 中:
注意:在 Vue 2 中,this
关键字在组件内部指向当前组件对象,而不是 Vue 的根实例(app 对象)。当你在 Vue 2 的组件中使用 this
,你实际上引用的是当前组件的上下文,包括组件的数据、方法、计算属性等。
this.$api.user...
let abc = this.$abc //111
为什么在全局定义了$abc,在组件里面就可以取到呢?
在 Vue 2 中,当你在 Vue 的原型对象 Vue.prototype
上定义了属性或方法,这些属性或方法会被添加到每个 Vue 组件实例上,因为 Vue 组件是通过构造函数创建的。
所以,当你在 Vue 2 中定义了 Vue.prototype.$abc = 111
,这个属性 $abc
就会被添加到每个 Vue 组件实例上。当你在组件内部使用 this.$abc
时,this
指向当前组件实例,因此你可以访问到这个在原型上定义的属性。
这是 Vue 2 提供的一种在全局范围内共享数据、方法的方式,你可以通过原型扩展来在每个组件中共享一些公共的数据或方法。
二、vue3.0
1、main.js 中
const app = createApp(App)
//全局配置
app.config.globalProperties.foo = 'bar'
2、.vue 文件中:
2.1 选项式 api:mounted 中(和 2.0 中用法一样)
但是 3.0 中很少使用 mounted
let abc = this.foo //bar
2.2 组合式 api:setup 中 (重头戏)
(1)使用 ctx (强烈不推荐!) ——> 获取当前组件实例,相当于 this
import { getCurrentInstance } from "vue";
const { ctx } = getCurrentInstance();
经过测试,打包到 dist 以后,ctx 下面的值是拿不到的,但是本地可以!
==(2)使用 proxy (强烈推荐)== ——> 获取当前组件实例,相当于 this
注意:proxy
是当前组件的代理对象,而不是整个 Vue 对象。在 Vue 3 中,组件实例是通过 createComponentInstance
创建的,每个组件实例都有自己的代理对象,这个代理对象是一个响应式的代理,可以通过它访问和操作组件的数据、计算属性、方法等。
setup() {
const { proxy, ctx } = getCurrentInstance()
const showMessage = () => {
let m = proxy.foo
let n = ctx.foo
ElMessage.success({
message: 'proxy: '+m, //本地和打包出来都可以拿到
type: 'success'
})
ElNotification({
title: 'ctx: '+n, //打包出来以后,内容拿不到
})
}
return {
showMessage
}
}
==(3)使用 appContext.config.globalProperties(推荐)== ——> 实际上 appContext 就是全局 app 对象!
const { appContext } = getCurrentInstance();
const globalProperties = appContext.config.globalProperties;
console.log(globalProperties.foo);
3、proxy、ctx、appContext 三者的区别
在 Vue 3 中,getCurrentInstance
是一个用于在组件内部获取当前组件实例的方法。它返回一个对象,该对象包含三个重要的属性:proxy
、ctx
、和appContext
。
proxy
:proxy
属性是一个代理对象,它暴露了组件实例的属性和方法。你可以通过这个代理对象来访问和操作组件实例的数据、方法、计算属性等。它使你能够在组件内部访问和操作组件的所有内容,而无需直接引用组件实例本身。这有助于提高代码的可维护性和可读性。ctx
:ctx
属性是一个上下文对象,它包含了一些常用的属性和方法,可以在组件的生命周期内使用。它包括了以下属性和方法:attrs
: 一个包含组件接收的父组件传递的非响应式属性的对象。slots
: 一个包含插槽内容的对象。emit
: 一个用于触发当前组件的自定义事件的函数。expose
: 允许你将一些属性或方法暴露给父组件。
appContext
:appContext
属性是一个应用程序上下文对象,它包含了与应用程序相关的全局属性和方法。通过这个属性,你可以访问全局配置、组件库、自定义指令、混入等。它通常在组件内部不直接使用,而是在需要访问全局内容时使用。
三者的应用场景:
这三个属性(proxy
、ctx
、appContext
)在 Vue 3 中有不同的应用场景,让我们更详细地探讨一下它们的用途:
proxy
的应用场景:- 数据访问与修改: 使用
proxy
,你可以访问和修改组件的响应式数据、计算属性和方法,而无需直接引用组件实例。这提高了代码的可读性,同时也使得在组件内部进行数据操作更加方便。
- 数据访问与修改: 使用
ctx
的应用场景:- 传递属性和插槽内容:
ctx
提供了一种方式来访问父组件传递给当前组件的属性,以及访问插槽内容。这对于自定义组件的封装非常有用,可以在组件内部访问这些数据。 - 触发自定义事件: 通过
ctx.emit
,你可以在组件内部触发自定义事件,这使得组件与其父组件之间能够进行通信。
- 传递属性和插槽内容:
appContext
的应用场景:- 全局配置和组件库: 你可以使用
appContext
来访问全局的配置项,如全局的混入、自定义指令、全局组件等。这允许你在组件内部访问这些全局资源,而不需要在每个组件中重复定义。 - 扩展插件功能: 如果你在应用中使用了自定义插件,那么这些插件可能会将一些功能添加到
appContext
中,供组件使用。
- 全局配置和组件库: 你可以使用
4、proxy 的实际应用:爱旅游


这样就获取了当前 ref 为 detailPanel 的子组件实例对象!
使用 proxy 和使用 ref 的区别:
const myComponentRef = ref(null); 和 getCurrentInstance().proxy.$refs.myComponentRef 的区别?
ref
创建的引用(reference)和通过 getCurrentInstance().proxy.$refs
获取的引用,在某种程度上是相似的。两种方法都可以用来引用组件实例。
主要区别在于,使用 ref
创建的引用需要你自己在组件中设置,而使用 $refs
是 Vue 在底层自动创建和管理的。此外,使用 $refs
会更适合在模板中直接使用,而使用 ref
更适合在组件的 setup
中使用。
无论选择哪种方法,都应该注意不要过度依赖对组件实例的直接引用,因为这可能导致代码的耦合性增加。最好的实践是使用 props 和事件来进行组件之间的通信,以保持组件的独立性和可维护性。
注意:就是写法不同,但是 proxy 除了具有$refs 还有其他的,所以更强大一些!