vue3中g(shù)etCurrentInstance不推薦使用及在<script?setup>中獲取全局內(nèi)容的三種方式
在vue3中并沒有暴露出一個(gè)獲取全局方法的的接口
所以我們并不能通過 import {全局方法} from 'vue' 的方法來獲取
首先在main.js中定義全局的內(nèi)容
const app = createApp(App) app.config.globalProperties.$test = '666' app.mount('#app')
方法一(不推薦)
vue 中的 getCurrentInstance 方法返回了 ctx 和 proxy,控制臺(tái)打印 ctx 和 proxy 發(fā)現(xiàn)和 vue2.x 中的 this 等同,習(xí)慣使用 this 的朋友可以用 proxy 進(jìn)行替代。
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 方法區(qū)獲取
const ctx = getCurrentInstance() console.log('ctx', ctx)
這時(shí)我們就能在控制臺(tái)中看到我們定義的內(nèi)容了
但是不推薦使用,不推薦原因其實(shí)在官網(wǎng)中已經(jīng)說的很明白了
官方解說: 在 setup() 內(nèi)部,this 不會(huì)是該活躍實(shí)例的引用(即不指向vue實(shí)例),因?yàn)?setup() 是在解析其它組件選項(xiàng)之前被調(diào)用的,所以 setup() 內(nèi)部的 this 的行為與其它選項(xiàng)中的 this 完全不同。這在和其它選項(xiàng)式 API 一起使用 setup() 時(shí)可能會(huì)導(dǎo)致混淆。因此setup函數(shù)中不能使用this。所以Vue為了避免我們錯(cuò)誤的使用,直接將setup函數(shù)中的this修改成了 undefined)
我理解: 在Vue3中,setup 在生命周期 beforecreate 和 created 前執(zhí)行,此時(shí) vue 對(duì)象還未創(chuàng)建,因此,無法使用我們?cè)?vue2.x 常用的 this。在生產(chǎn)環(huán)境內(nèi)可能會(huì)獲取不到該實(shí)例!!,而且我們確實(shí)不應(yīng)該用該方法去代替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.
同時(shí)也給出了應(yīng)該如何解決問題:
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 是一個(gè)內(nèi)部的API,并不是公開的API,使用內(nèi)部API去實(shí)現(xiàn)一些業(yè)務(wù)功能,可能會(huì)因?yàn)楹罄m(xù) Vue 的版本迭代而造成業(yè)務(wù)上的 BUG。并且 Vue3 的 Composition API 強(qiáng)調(diào)的就是業(yè)務(wù)的解耦和復(fù)用性,依賴組件實(shí)例屬性并不是一個(gè)很好的開發(fā)方式。而 vue 相關(guān)生態(tài)的使用其實(shí)就是他們內(nèi)部的事情了,他們有完善的測(cè)試用例可以跑測(cè)試,但是我們并沒有,如果后續(xù)的某一個(gè)版本Vue變更了這個(gè)API,那么如果沒有經(jīng)過完整測(cè)試就部署上去的項(xiàng)目就會(huì)出現(xiàn)大規(guī)模的BUG反饋了。
vue3 github issu反饋截圖
魷魚須反饋截圖
方法二(推薦)
使用 Provide / Inject
v3.cn.vuejs.org/guide/compo… 在main.js中provide app.provide('$test', '666')
在組件內(nèi)獲取
import { inject } from 'vue' const test = inject('$test') console.log('inject的$test', test) 這樣就可以獲取到了
擴(kuò)展
掛載方法 在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)
方式三(不推薦 只適合應(yīng)急的時(shí)候使用 因?yàn)槲矣X得這樣用怪怪的)
使用兩個(gè)script標(biāo)簽來獲取this并保存
首先現(xiàn)在main.js中像之前一樣定義全局變量
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // 官方推薦將全局變量寫進(jìn) globalProperties下 app.config.globalProperties.myOption = 'myOption' app.mount('#app') 然后在組件中獲取 <script> import HelloWorld from './components/HelloWorld.vue' import { onBeforeMount, defineComponent } from 'vue' let that = this export default defineComponent({ beforeCreate() { that = this }, }) </script> <script setup> onBeforeMount(() => { console.log('that', that.myOption) }) </script> 這樣就可以獲取到啦
在setup標(biāo)簽中一定要在 onBeforeMount之后再讀取this?。。?/p>
一些問題
為什么要?jiǎng)?chuàng)建兩個(gè)script標(biāo)簽?
因?yàn)樵趕etup標(biāo)簽中是不綁定this的 所以只能在另一個(gè)script標(biāo)簽中獲取
為什么一定要在onBeforeMount之后才能獲取呢?
因?yàn)閟etup的生命周期是在beforeCreate,created之前執(zhí)行的 我們?cè)赽eforeCreate時(shí)保存的this,所以要在beforeCreate之后獲取,onBeforeMount是在beforeCreate之后執(zhí)行的 所以可以獲取到 note
如果按這樣寫了兩個(gè)script標(biāo)簽?zāi)敲淳筒豢梢栽跊]寫setup中再執(zhí)行setup函數(shù)
<script> import HelloWorld from './components/HelloWorld.vue' import { onBeforeMount, defineComponent } from 'vue' let that = this export default defineComponent({ beforeCreate() { console.log('beforeCreate') that = this }, setup() { // 這里面的內(nèi)容不會(huì)執(zhí)行 console.log('非單標(biāo)簽的setup') } }) </script> <script setup> console.log('setup') onBeforeMount(() => { console.log('that', that.myOption) }) </script>
為啥
因?yàn)樵跇?biāo)簽中寫setup本身就是一個(gè)語法糖 vue會(huì)檢驗(yàn)是否有
// 這是options方式
<script> import HelloWorld from './components/HelloWorld.vue' export default defineComponent({ setup() { // 這里面的內(nèi)容還是不會(huì)執(zhí)行 console.log('非單標(biāo)簽的setup') } }) </script> // 這是<script setup> <script setup></script>
你可能回想(會(huì)不會(huì)是因?yàn)?setup標(biāo)簽放到下方 所以覆蓋了上方的setup方法呢?) 經(jīng)測(cè)試 這個(gè)執(zhí)行方式無關(guān)你放置的位置 哪怕將其放到options方式上方他仍然不會(huì)執(zhí)行!
總結(jié)
到此這篇關(guān)于vue3中g(shù)etCurrentInstance不推薦使用及在<script setup>中獲取全局內(nèi)容的三種方式的文章就介紹到這了,更多相關(guān)vue3在<script setup>獲取全局內(nèi)容內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue.JS實(shí)現(xiàn)垂直方向展開、收縮不定高度模塊的JS組件
這篇文章主要介紹了Vue.JS實(shí)現(xiàn)垂直方向展開、收縮不定高度模塊的JS組件,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06vue學(xué)習(xí)筆記之v-if和v-show的區(qū)別
本篇文章主要介紹了vue學(xué)習(xí)筆記之v-if和v-show的區(qū)別,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09vue 路由視圖 router-view嵌套跳轉(zhuǎn)的實(shí)現(xiàn)
這篇文章主要介紹了vue 路由視圖 router-view嵌套跳轉(zhuǎn),主要實(shí)現(xiàn)的內(nèi)容有制作一個(gè)登錄頁面,跳轉(zhuǎn)到首頁,首頁包含菜單欄、頂部導(dǎo)航欄、主體,標(biāo)準(zhǔn)的后臺(tái)網(wǎng)頁格式,菜單點(diǎn)擊顯示不同的頁面,感興趣的小伙伴請(qǐng)參考下面文章內(nèi)容2021-09-09