35

Anybody know how to do add a global variable in Vue 3 ?

in Vue 2 we use this in the main.js file:

Vue.prototype.$myGlobalVariable = globalVariable
Boussadjra Brahim
  • 64,851
  • 14
  • 107
  • 134
Adri HM
  • 1,183
  • 2
  • 12
  • 21

6 Answers6

38

The most direct replacement is app.config.globalProperties. See:

https://v3.vuejs.org/api/application-config.html#globalproperties

So:

Vue.prototype.$myGlobalVariable = globalVariable

becomes:

const app = Vue.createApp({})
app.config.globalProperties.$myGlobalVariable = globalVariable

Note that this is scoped to a particular application rather than being global as it was with Vue.prototype. This is by design, all global configuration options are now scoped to an application.

The relevant RFC is here:

https://github.com/vuejs/rfcs/blob/master/active-rfcs/0009-global-api-change.md

Note that application-level provide/inject (also discussed in that RFC) is also an alternative to using Vue.prototype:

const app = Vue.createApp({})

app.provide('myGlobalVariable', globalVariable)

// In the descendant component
export default {
  inject: ['myGlobalVariable']
}

Docs: https://v3.vuejs.org/api/application-api.html#provide

The idea here is that the component can explicitly declare the property rather than inheriting it by magic. That avoids problems like name collisions, so there's no need to use a $ prefix. It can also help to make it clearer where exactly a property is coming from.

Which approach you prefer will depend on your circumstances.

skirtle
  • 25,240
  • 3
  • 33
  • 53
  • does this work with classes? doesn't seem to work for me – David 天宇 Wong Sep 12 '21 at 04:30
  • And how are the global variables accessed from the child components (In both cases)? Is it directly by calling `this.myGlobalVariable`? – M3HD1 Dec 15 '21 at 08:10
  • Is there a way to declare global variables from outside the main app creation file? In Vue 2 I used to import Vue and then declare new global variables. I am struggling now since I need the `app` created by `createApp`. – M3HD1 Dec 15 '21 at 08:17
  • M3HD1 - You can create a function that takes the application (`app` in the code above) as a parameter and does the `provide` (i.e. doProv = function(app) { app.provide(...); } and then just import it and call it in main.js or wherever you do your app creation/setup. – Dov Rosenberg Jan 23 '22 at 13:41
21

I recommend to use provide/inject approach as follows :

in main.js :

import {createApp} from 'vue'

let app=createApp({
  provide:{
    globalVariable:123
  }

}).$mount('#app')

in some child or grand-child component do :

export default{
 name:'some-compo',
 inject:['globalVariable'],
 //then access this.globalVariable as property in you component
...
}

for composition api and script setup :

 import { inject } from 'vue'
 
 let globalVar=inject('globalVariable')
Boussadjra Brahim
  • 64,851
  • 14
  • 107
  • 134
  • 1
    createApp in my example is being passed a component, which has – David 天宇 Wong Sep 12 '21 at 04:19
  • how can i achieve something similar to this inside a class ( not a component ) i mean how can i use inject inside a class ? – yasseros Nov 12 '21 at 10:31
  • Is it possible to inject multiple variables in one line? – W.M. Jan 05 '22 at 20:17
  • 1
    @W.M. yes you could with options api, but in composition one you should assign each injected item in a specific variable – Boussadjra Brahim Jan 05 '22 at 21:28
  • I have done it like this, `const global = {"$axios": axios,'$moment': moment,'$third': third,}; app.provide('$global ', global );` in `main.js`, and then inject the whole object when needed. – W.M. Jan 07 '22 at 18:04
16

How to add a global variable using Vue 3 and vue-cli (or Vite)

Note: You can drop the dollar sign from your $globalVariable and just use globalVariable, just like in the documentation.

Initially your main.js file looks something like this (adding router for common use case):

import { createApp } from 'vue'
import { App } from './App.vue'
import { router } from './router'

createApp(App).use(router).mount('#app')

To use add the global variable using Vue 3 and the vue-cli or Vite:

import { createApp } from 'vue'
import { App } from './App.vue'
import { router } from './router'

// 1. Assign app to a variable
let app = createApp(App)

// 2. Assign the global variable before mounting
app.config.globalProperties.globalVar = 'globalVar'

// 3. Use router and mount app
app.use(router).mount('#app')

Then to access the variables in components like this:

<script>
export default {
    data() {
        return {
            myVar: this.globalVar
        }
    }
}
</script>

like in the template like this:

<template>
  <h1>{{ globalVar }}</h1>
</template>

And that's it. Happy coding!

About Global Variables and Composition API

According to the very bottom of samayo's answer on this post, global variables are only available on the Options API.

Quoting the bottom of his answer:

Note: This is only for the Options API. Evan You (Vue creator) says: "config.globalProperties are meant as an escape hatch for replicating the behavior of Vue.prototype. In setup functions, simply import what you need or explicitly use provide/inject to expose properties to app.

Zack Plauché
  • 1,964
  • 9
  • 24
  • 1
    hey that's amazing!! thank you very much!! =) – zergski Sep 29 '21 at 19:03
  • 1
    Prefixing variables with some kind of "special character" makes it easier to signify in code that this variable is indeed special and probably comes from somewhere else. This makes coders more aware and development less error-prone. – Coreus Nov 09 '21 at 13:16
  • @Coreus is there specific documentation that talks about this? – Zack Plauché Nov 10 '21 at 09:39
  • No, but it's a common practice for things that pollute the global scope. Think i.e jQuery for instance and their $. The approach was also commonly used in Vue 2 docs. As always, you're free to use whatever you want, in the same way you're free to drive off the side of the road instead of following it. You should probably look up the Rosetta Stone. Experience tells us that making them stand out (in some way) makes their significance easier to see. – Coreus Nov 16 '21 at 12:19
  • Why provide an example with the options API in Vue 3? One of the biggest reasons to move to Vue 3 is the composition API with the script setup sugar. – db2 Dec 22 '21 at 21:52
  • 1
    @db2 Just updated. Apparently this isn't a feature for the composition api. – Zack Plauché Dec 26 '21 at 19:13
8

If possible you should use imports or provide/inject. Another way to define global variables/functions and use them would be using globalProperties (although this seems to be considered more of an anti-pattern). But if a library you use uses globalProperties then you can use it like this. This also works with global functions.

const app = Vue.createApp({})
app.config.globalProperties.$http = () => {} // global function
app.config.globalProperties.$globalVariable = 'Jimmy' // global variable

1. Using options API

mounted() {
  console.log(this.$globalVariable)
}

2. Using setup method

<script setup>
    import { getCurrentInstance } from 'vue'

    const app = getCurrentInstance()
    const progressBar = app.appContext.config.globalProperties.$globalVariable

    console.log(this.$globalVariable)
</script>
Martin Zeltin
  • 1,262
  • 2
  • 12
  • 23
7

For those of you who are confused about how to access globalProperties in the setup() method, you can use getCurrentInstance() as in the following documentation.

https://v3.vuejs.org/api/composition-api.html#getcurrentinstance

ghosh
  • 1,314
  • 1
  • 14
  • 23
  • From the documentation: "getCurrentInstance is only exposed for advanced use cases, typically in libraries. Usage of getCurrentInstance is strongly discouraged in application code. Do NOT use it as an escape hatch to get the equivalent of this in Composition API." – Coreus Nov 09 '21 at 13:18
0

In my case I had to create a global var and get the data from a script.
Used provide and inject:

In main.js:

    import { createApp } from 'vue'
    import App from './App.vue'
    const app = createApp(App);
    app.provide('message',document.querySelector('script[name="nameSCRIPT"]').innerHTML.split('=').slice(1).join('=').slice(1,-1));
    app.mount('#app')

In index.html:

 <script name="nameSCRIPT">nameSCRIPT="HELLO"</script>

In child component:

    inject:['message'],
    mounted(){
    console.log(this.message)
  },
Zach Jensz
  • 2,608
  • 3
  • 8
  • 23
tastytim
  • 31
  • 2