vue3中getCurrentInstance不推荐使用以及在<script setup>中获取全局内容(三种方式)

16,928次阅读
没有评论

共计 3781 个字符,预计需要花费 10 分钟才能阅读完成。

在 vue3 中并没有暴露出一个获取全局方法的的接口
所以我们并不能通过 import {全局方法} from 'vue' 的方法来获取

首先在 main.js 中定义全局的内容
 const app = createApp(App)
 app.config.globalProperties.$test = '666'
 app.mount('#app')

方法一(不推荐)

vue 中的 getCurrentInstance 方法返回了 ctx 和 proxy,控制台打印 ctx 和 proxy 发现和 vue2.x 中的 this 等同,习惯使用 this 的朋友可以用 proxy 进行替代。

import {defineComponent, getCurrentInstance} from 'vue'
export default defineComponent ({setup(){
  
  	//vue3-typescript
    const {proxy, ctx} = (getCurrentInstance() as ComponentInternalInstance)
	//vue3-javascript
	const {proxy, ctx} = getCurrentInstance()
	
    const _this = ctx
    
    console.log('getCurrentInstance()中的 ctx:', _this)
    console.log('getCurrentInstance()中的 proxy:', proxy)
    
    return {}}
})

本例中使用 getCurrentInstance 方法区获取

const ctx = getCurrentInstance() console.log('ctx', ctx)

这时我们就能在控制台中看到我们定义的内容了
vue3 中 getCurrentInstance 不推荐使用以及在<script setup>中获取全局内容(三种方式)


但是不推荐使用,不推荐原因其实在官网中已经说的很明白了

vue3 中 getCurrentInstance 不推荐使用以及在<script setup>中获取全局内容(三种方式)

官方解说:在 setup() 内部,this 不会是该活跃实例的引用(即不指向 vue 实例),因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这在和其它选项式 API 一起使用 setup() 时可能会导致混淆。因此 setup 函数中不能使用 this。所以 Vue 为了避免我们错误的使用,直接将 setup 函数中的 this 修改成了 undefined)

我理解:在 Vue3 中,setup 在生命周期 beforecreate 和 created 前执行,此时 vue 对象还未创建,因此,无法使用我们在 vue2.x 常用的 this。在生产环境内可能会获取不到该实例!!, 而且我们确实不应该用该方法去代替 this

按照鱿鱼须的原话就是:

Because the instance is an internal instance that exposes non-public APIs. Anything you use from that instance can technically break between any release types, since they are not subject to semver constraints.

同时也给出了应该如何解决问题:

I’m not sure why you need the setup context in nested composables, but explicitly passing arguments to composables make then less coupled to the consuming component, thus easier to understand and test in isolation.

In general a library designed to work with Composition API should expose special variables via its own composables (e.g. useRoute from vue-router) instead of the requiring the user to grab it from the instance.

主要还是 getCurrentInstance 是一个内部的 API,并不是公开的 API,使用内部 API 去实现一些业务功能,可能会因为后续 Vue 的版本迭代而造成业务上的 BUG。并且 Vue3 的 Composition API 强调的就是业务的解耦和复用性,依赖组件实例属性并不是一个很好的开发方式。而 vue 相关生态的使用其实就是他们内部的事情了,他们有完善的测试用例可以跑测试,但是我们并没有,如果后续的某一个版本 Vue 变更了这个 API,那么如果没有经过完整测试就部署上去的项目就会出现大规模的 BUG 反馈了。

vue3 github issu 反馈截图
https://github.com/vuejs/docs…
vue3 中 getCurrentInstance 不推荐使用以及在<script setup>中获取全局内容(三种方式)

鱿鱼须反馈截图
vue3 中 getCurrentInstance 不推荐使用以及在<script setup>中获取全局内容(三种方式)

方法二(推荐)

使用 Provide / Inject

v3.cn.vuejs.org/guide/compo…
在 main.js 中 provide
app.provide('$test', '666')

在组件内获取

import {inject} from 'vue'
const test = inject('$test')
console.log('inject 的 $test', test)
这样就可以获取到了

扩展
挂载方法 在 main.js 中 provide

import dayjs from 'dayjs'
const formatTime = (time, format) => (time ? dayjs(time).format(format || 'YYYY-MM-DD') : '-')
app.provide('dayjs', formatTime)

在组件中获取
const dayjs = inject('dayjs')
const formatResult = dayjs(1639014286)
console.log('dayFormat', formatResult)

方式三(不推荐 只适合应急的时候使用 因为我觉得这样用怪怪的)

使用两个 script 标签来获取 this 并保存
首先现在 main.js 中像之前一样定义全局变量

import {createApp} from 'vue'
import App from './App.vue'
const app = createApp(App)
// 官方推荐将全局变量写进 globalProperties 下
app.config.globalProperties.myOption = 'myOption'
app.mount('#app')
然后在组件中获取


这样就可以获取到啦

在 setup 标签中一定要在 onBeforeMount 之后再读取 this!!!

一些问题

为什么要创建两个 script 标签?
因为在 setup 标签中是不绑定 this 的 所以只能在另一个 script 标签中获取
为什么一定要在 onBeforeMount 之后才能获取呢?
因为 setup 的生命周期是在 beforeCreate,created 之前执行的 我们在 beforeCreate 时保存的 this,所以要在 beforeCreate 之后获取,onBeforeMount 是在 beforeCreate 之后执行的 所以可以获取到 note
如果按这样写了两个 script 标签那么就不可以在没写 setup 中再执行 setup 函数
xml
复制代码



为啥
因为在标签中写 setup 本身就是一个语法糖 vue 会检验是否有

// 这是 options 方式


// 这是

你可能回想(会不会是因为 setup 标签放到下方 所以覆盖了上方的 setup 方法呢?) 经测试 这个执行方式无关你放置的位置 哪怕将其放到 options 方式上方他仍然不会执行!

原文地址: vue3 中 getCurrentInstance 不推荐使用以及在

正文完
 0
Yojack
版权声明:本篇文章由 Yojack 于2025-02-01发表,共计3781字。
转载说明:
1 本网站名称:优杰开发笔记
2 本站永久网址:https://yojack.cn
3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5 本站所有内容均可转载及分享, 但请注明出处
6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
7 站长邮箱:laylwenl@gmail.com
评论(没有评论)