在 Vue.js 3 setup() 中访问 this.$root

Access this.$root in Vue.js 3 setup()

在 Vue 2 中,您可以在 created 挂钩中访问 this.$root。在 Vue 3 中,所有会进入 created 钩子的东西现在都进入了 setup().

setup() 中我们无法访问 this,那么,我们如何访问根实例上的任何内容?

说,我在根实例上设置了一个 属性:

const app = createApp(App).mount('#app');

app.$appName = 'Vue3';

我可以使用 this.$root.$appNamemounted() 访问 this,我如何在 setup() 中执行此操作?


更新

我可以访问它,如果我 import 它:

import app from '@/main';
...
setup() {
    console.log(app.$appName) // Vue3

但是,如果我必须对每个文件都这样做,这会很麻烦。


更新 2

另一种解决方法是在 App.vue 中使用 provide(),然后在任何其他组件中使用 inject()

setup() {
    provide('$appName', 'Vue3')
setup() {
    inject('$appName') // Vue3

看来你需要provide / inject。在你的 App.vue:

import { provide } from 'vue';

export default {
  setup() {
    provide('appName', 'vue3')
  }
} 

provide它与你的app:

const app = createApp(App);
app.mount('#app');

app.provide('appName', 'Vue3');

然后在您要访问此变量的任何子组件中,inject它:

import { inject } from 'vue'

export default {
  setup() {
    const appName = inject('appName');
  }
}

你可以在 vue 3 中定义 global property :

app.config.globalProperties.appName= 'vue3'

使用 setup(组合 api),您可以使用 getcurrentinstance 访问 属性:

import { getCurrentInstance } from 'vue'
...
setup() {
    const app= getCurrentInstance()
    console.log(app.appContext.config.globalProperties.appName) 

由于您仍然可以使用选项 api,您可以简单地执行以下操作:

mounted(){
   console.log(this.appName) 
}

对于想知道如何在 setup() 中访问 this 的任何人,一种方法是将 this 设置为 created() 挂钩中的记忆变量并使用 nextTick() 访问它:

const app = createApp(App);

app.config.globalProperties.$appName = 'Hello!';
<script>
import { nextTick } from 'vue';

let self;

export default {
    name: 'HelloWorld',

    setup() {
        nextTick(() => console.log(self.$appName)); // 'Hello!'
    },

    created() {
        self = this;
    },
};
</script>

在我看来是更好的做法,但是,这只是另一种方式。

如果您只想将任何模板中的 {{ appName }} 替换为 'Vue 3'(字符串),而无需导入任何内容,最干净的方法是使用 config.globalProperties,如其他答案建议:

const app = createApp(App).mount('#app');
app.config.globalProperties.appName = 'Vue 3'

但是,您应该尽量不要过度使用这个模式。它违背了推动 Composition 发展的可重用性和模块化原则 API.

你应该避免污染的主要原因 globalProperties 是因为它在 Vue3 应用程序中充当污染场,所以许多插件开发者可能决定使用它来提供他们的插件实例。 (显然,没有人会命名插件 appName,因此您 运行 在这种特殊情况下没有风险)。

推荐的全球化替代方法是导出 useStuff() 函数。
在你的情况下:

export function useAppName () { return 'Vue 3' }
// or even:
export const useAppName = () => 'Vue 3'

在任何组件中:

import { useAppName } from '@/path/to/function'

setup () {
   const appName = useAppName()
   return {
     appName // make it available in template and hooks
   }
}

优点:

  • 它使用组合 API 命名约定
  • 当共享比原语更复杂的东西时(可以是一个模块、一组函数、一项服务等...)所有类型 是开箱即用的推断。这在 setup() 函数中特别有用。
  • 您只在需要公开的地方公开和确定 stuff 的范围,而不是在应用的每个组件中公开。另一个优点是:如果你只在 setup() 函数中需要它,你不必将它暴露给模板或钩子。

使用随机(但真实)插件的示例:
创建插件文件(即:/plugins/gsap.ts):

import gsap from 'gsap'
import ScrollToPlugin from 'gsap/ScrollToPlugin'

// configure the plugin globally
gsap.registerPlugin(ScrollToPlugin)

export function useGsap () {
  return gsap
}

在任何组件中:

import { defineComponent } from 'vue'
import { useGsap } from '@/plugins/gsap'

export defineComponent({
  setup () {
    const gsap = useGsap()
      // gsap here is typed correctly (if the plugin has typings)
      // no need for casting
    return { 
      gsap  // optionally provide it to hooks and template
    }       // if needed outside setup()
  }
})