Nikola Pavicevic
Nikola Pavicevic

Reputation: 23480

Vue3 use global variable in js files

I have some global variables in Vue3 project defined like:

 app.config.globalproperties.$locale = locale

then composable is created to dynamically return global variable:

import { getCurrentInstance ) from 'vue'
export function useGlobals(type) {
  const app = getCurrentInstance()
  const global = app.appContext.config.globalProperties[`$${type}`]
  return { global }
}

then in vue components composable is imported and executed:

import { useGlobals } from '../path'
const { global } = useGlobals('locale')

now, global variable can be used.

But the problem arise when I import composable in js files, there the appContext is undefined.

My question is, is there a way we can get global variable or appContext in js files?

Upvotes: 8

Views: 6480

Answers (3)

Nelson
Nelson

Reputation: 71

I attempted the answer suggested by @nikola-pavicevic, but it had a negative side effect of causing infinite recursion. For example, every time you import globals, it has to run through the entirety of main.js, which means initializing and mounting the app again. In production, the app appears to work correctly most of the time, but in my Jest unit tests, the recursion causes lots of issues.

To get around this, I created a GlobalVariableHolder.js file that only contains the following:

const GlobalVariables = {};
export default GlobalVariables;

Then, in main.js, I can import it like so:

import GlobalVariables from "./GlobalVariableHolder";

Then assign the variables:

// This line expects that you first assigned the variables to app.config.globalProperties.
GlobalVariables.variables = app.config.globalProperties;

Then, in the JS file where you need them, your import looks the same as before:

import GlobalVariables from "./GlobalVariableHolder";

And you have access to everything that was in app.config.globalProperties like this:

GlobalVariables.variables.$thisIsAMethod(parameter);

This way, importing GlobalVariableHolder doesn't spin up a new Vue instance every time.

Upvotes: 2

Nikola Pavicevic
Nikola Pavicevic

Reputation: 23480

Thanks to great suggestion from @tao (btw it is impossible to get appContext from app but that gives me an idea :)) issue is solved.

I created another export in main.js, after app creation, with the all global properties:

const globals = app.config.globalProperties
export { globals }

or as a function (another @tao suggestion):

export const useGlobals = () => app.config.globalProperties

Now we can import globals in any js file and use it like:

import { globals } from '../path/to/main.js'
globals.$locale

or from function :

import { useGlobals } from '../path/to/main.js'
const { $locale } = useGlobals()

Upvotes: 5

Mossaab
Mossaab

Reputation: 66

instead of creating your composable to get global props, you can use the provide/inject mechanism.

check the documentation here: https://vuejs.org/api/composition-api-dependency-injection.html#provide

Upvotes: 0

Related Questions