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

Dan*_*hts 9 javascript vue.js vue-component vuejs3 vue-composition-api

在 Vue 2 中,您可以访问钩子this.$root内部created。在 Vue 3 中,原本应该进入createdhook 的所有东西现在都进入了setup().

setup()我们没有访问权限的情况下this,我们如何访问根实例上的任何内容?

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

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

app.$appName = 'Vue3';
Run Code Online (Sandbox Code Playgroud)

我可以thismounted()with访问this.$root.$appName,我怎样才能做到这一点setup()


更新

如果我可以访问import它:

import app from '@/main';
...
setup() {
    console.log(app.$appName) // Vue3
Run Code Online (Sandbox Code Playgroud)

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


更新 2

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

setup() {
    provide('$appName', 'Vue3')
Run Code Online (Sandbox Code Playgroud)
setup() {
    inject('$appName') // Vue3
Run Code Online (Sandbox Code Playgroud)

Bou*_*him 15

您可以在 vue 3 中定义全局属性

app.config.globalProperties.appName= 'vue3'
Run Code Online (Sandbox Code Playgroud)

使用setup(composition api) 您可以使用getcurrentinstance来访问该属性:

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

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

mounted(){
   console.log(this.appName) 
}
Run Code Online (Sandbox Code Playgroud)


Psi*_*dom 8

看来您需要提供/注入。在您的App.vue

import { provide } from 'vue';

export default {
  setup() {
    provide('appName', 'vue3')
  }
} 
Run Code Online (Sandbox Code Playgroud)

或者provide它与您的app

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

app.provide('appName', 'Vue3');
Run Code Online (Sandbox Code Playgroud)

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

import { inject } from 'vue'

export default {
  setup() {
    const appName = inject('appName');
  }
}
Run Code Online (Sandbox Code Playgroud)


And*_*hiu 5

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

const app = createApp(App).mount('#app');
app.config.globalProperties.appName = 'Vue 3'
Run Code Online (Sandbox Code Playgroud)

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

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

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

export function useAppName () { return 'Vue 3' }
// or even:
export const useAppName = () => 'Vue 3'
Run Code Online (Sandbox Code Playgroud)

在任何组件中:

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

setup () {
   const appName = useAppName()
   return {
     appName // make it available in template and hooks
   }
}
Run Code Online (Sandbox Code Playgroud)

优点:

  • 它使用 Composition 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
}
Run Code Online (Sandbox Code Playgroud)

在任何组件中:

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()
  }
})
Run Code Online (Sandbox Code Playgroud)