Agregar variable global en Vue.js 3

10 minutos de lectura

Avatar de usuario de Adri HM
Adri H. M.

¿Alguien sabe cómo agregar una variable global en Vue 3?

en Vue 2 usamos esto en el main.js archivo:

Vue.prototype.$myGlobalVariable = globalVariable

  • stackoverflow.com/a/40897670/2815635

    – Niklesh Raut

    26 de julio de 2020 a las 13:19

  • Puede usar Vuex para manejar todos los datos globales

    – nassim miled

    26 de julio de 2020 a las 13:20

  • Sí, por supuesto, puedo usar la tienda o usar una combinación global, pero estoy pidiendo usar un prototipo.

    – Adri HM

    26 de julio de 2020 a las 13:21

avatar de usuario de skirtle
falda

El reemplazo más directo es app.config.globalProperties. Ver:

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

Entonces:

Vue.prototype.$myGlobalVariable = globalVariable

se convierte en:

const app = createApp(RootComponent)
app.config.globalProperties.$myGlobalVariable = globalVariable

Esto está enfocado a una aplicación particular en lugar de ser global como lo fue con Vue.prototype. Esto es por diseño, todas las opciones de configuración ‘globales’ ahora están en el ámbito de una aplicación.

El RFC relevante está aquí:

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

Propiedades añadidas a globalProperties estará disponible a través de la instancia del componente para todos los componentes dentro de la aplicación. Entonces, si está utilizando la API de opciones, podrá acceder a ellas usando this.$myGlobalVariableal igual que podrías con Vue.prototype. También estarán disponibles en la plantilla sin la this.p.ej {{ $myGlobalVariable }}.

Si está utilizando la API de composición, aún podrá usar estas propiedades dentro de la plantilla, pero no tendrá acceso a la instancia del componente dentro setuppor lo que no se podrá acceder a estas propiedades allí.

Mientras que los hacks que involucran getCurrentInstance() se puede utilizar para acceder globalProperties dentro setupesos hacks implican el uso de API no documentadas y no son el enfoque recomendado.

En cambio, a nivel de aplicación provide/inject (también discutido en ese RFC) se puede utilizar como una alternativa a Vue.prototype:

const app = createApp(RootComponent)
app.provide('myGlobalVariable', globalVariable)

En el componente descendiente, se puede acceder a esto usando inject. por ejemplo, con <script setup>:

<script setup>
import { inject } from 'vue'
const myGlobalVariable = inject('myGlobalVariable')
</script>

O con un explícito setup función:

import { inject } from 'vue'

export default {
  setup() {
    const myGlobalVariable = inject('myGlobalVariable')

    // Expose it to the template, if required
    return {
      myGlobalVariable
    }
  }
}

O con la API de Opciones:

export default {
  inject: ['myGlobalVariable']
}

Documentos: https://vuejs.org/api/application.html#app-provide

La idea aquí es que el componente pueda declarar explícitamente la propiedad en lugar de heredarla por arte de magia. Eso evita problemas como colisiones de nombres, por lo que no es necesario utilizar un $ prefijo. También puede ayudar a aclarar de dónde proviene exactamente una propiedad.

Es común para el inject función para ser envuelto en un componible. por ejemplo, el useRoute componible expuesto por Vue Router es solo un envoltorio inject.

Además de globalProperties y provide/injecthay varias otras técnicas que podrían usarse para resolver los mismos problemas que Vue.prototype. Por ejemplo, módulos ES, tiendas o incluso mixins globales. Estas no son necesariamente respuestas directas a la pregunta específica publicada aquí, pero he entrado en más detalles describiendo los diversos enfoques en:

https://skirtles-code.github.io/vue-examples/patterns/global-properties.html

El enfoque que prefiera dependerá de sus circunstancias.

  • esto funciona con las clases? no parece funcionar para mí

    – David 天宇 Wong

    12 de septiembre de 2021 a las 4:30

  • ¿Y cómo se accede a las variables globales desde los componentes secundarios (en ambos casos)? es directamente llamando this.myGlobalVariable?

    – Mehdi

    15 de diciembre de 2021 a las 8:10

  • ¿Hay alguna forma de declarar variables globales desde fuera del archivo de creación de la aplicación principal? En Vue 2 solía importar Vue y luego declarar nuevas variables globales. Estoy luchando ahora ya que necesito el app creado por createApp.

    – Mehdi

    15 de diciembre de 2021 a las 8:17

  • M3HD1: puede crear una función que tome la aplicación (app en el código anterior) como un parámetro y hace el provide (es decir, doProv = function(app) { app.provide(…); } y luego simplemente impórtelo y llámelo en main.js o donde sea que haga la creación/configuración de su aplicación.

    – Dov Rosenberg

    23 de enero de 2022 a las 13:41

  • Su argumentación es sólida, pero notablemente no enfatiza la gran desventaja del nuevo enfoque. Necesitas una línea extra, es decir injecten cada componente en el que desee acceder a una variable global en CAPI.

    – ViBoNaCci

    19 de marzo a las 8:34

Avatar de usuario de Zack Plauché
Zack Plauche

Cómo agregar una variable global usando Vue 3 y vue-cli (o Vite)

Nota: Puede soltar el signo de dólar de su $globalVariable y solo usa globalVariableal igual que en la documentación.

Inicialmente, su archivo main.js se parece a esto (agregando enrutador para un caso de uso común):

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

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

Para usar agregar la variable global usando Vue 3 y el vue-cli o 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')

Luego, para acceder a las variables en componentes como este:

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

como en la plantilla como esta:

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

Y eso es. ¡Feliz codificación!

Acerca de las variables globales y la API de composición

De acuerdo con la muy parte inferior de la respuesta de samayo en este postlas variables globales solo están disponibles en la API de opciones.

Citando la parte inferior de su respuesta:

Nota: Esto es solo para la API de opciones. Evan You (creador de Vue) dice: “config.globalProperties está pensada como una vía de escape para replicar el comportamiento de Vue.prototype. En las funciones de configuración, simplemente importe lo que necesita o use explícitamente proporcionar/inyectar para exponer las propiedades en la aplicación.

  • oye eso es increible!! ¡¡muchas gracias!! =)

    – zergski

    29 sep 2021 a las 19:03

  • Prefijar las variables con algún tipo de “carácter especial” hace que sea más fácil indicar en el código que esta variable es realmente especial y probablemente proviene de otro lugar. Esto hace que los codificadores sean más conscientes y que el desarrollo sea menos propenso a errores.

    – Coreo

    9 de noviembre de 2021 a las 13:16

  • @Coreus, ¿hay documentación específica que hable sobre esto?

    – Zack Plauché

    10 de noviembre de 2021 a las 9:39

  • No, pero es una práctica común para las cosas que contaminan el ámbito global. Piense en jQuery, por ejemplo, y su $. El enfoque también se usó comúnmente en los documentos de Vue 2. Como siempre, eres libre de usar lo que quieras, de la misma manera que eres libre de salirte del camino en lugar de seguirlo. Probablemente deberías buscar la Piedra de Rosetta. La experiencia nos dice que hacer que se destaquen (de alguna manera) hace que su significado sea más fácil de ver.

    – Coreo

    16 de noviembre de 2021 a las 12:19


  • @db2 Recién actualizado. Aparentemente, esta no es una función para la API de composición.

    – Zack Plauché

    26 de diciembre de 2021 a las 19:13

Avatar de usuario de Boussadjra Brahim
Boussadjra Brahim

recomiendo usar provide/inject enfoque de la siguiente manera:

en principal.js:

import {createApp} from 'vue'

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

}).$mount('#app')

en algún componente hijo o nieto hacer:

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

para la composición de la API y la configuración del script:

 import { inject } from 'vue'
 
 let globalVar=inject('globalVariable')

  • createApp en mi ejemplo se le está pasando un componente, que tiene . Entonces, ¿cómo pasar proporcionar en este caso?

    – David 天宇 Wong

    12 de septiembre de 2021 a las 4:19

  • ¿Cómo puedo lograr algo similar a esto dentro de una clase (no un componente), quiero decir, cómo puedo usar inyectar dentro de una clase?

    – yasseros

    12 de noviembre de 2021 a las 10:31

  • ¿Es posible inyectar múltiples variables en una línea?

    – WM

    5 de enero de 2022 a las 20:17

  • @WM, sí, podría con las opciones api, pero en la composición uno debe asignar cada elemento inyectado en una variable específica

    – Boussadjra Brahim

    5 de enero de 2022 a las 21:28

  • Actualmente solo está vinculando a la página de proporcionar/inyectar API de opciones, también debe vincular a la página de proporcionar/inyectar API de composición: vuejs.org/api/composition-api-dependencia-inyección.html

    usuario17408941

    7 de julio de 2022 a las 12:27

Si es posible, debe usar importaciones o proporcionar/inyectar. Otra forma de definir variables/funciones globales y usarlas sería usando globalProperties (aunque esto parece considerarse más como un antipatrón). Pero si una biblioteca que usa usa globalProperties, entonces puede usarla así. Esto también funciona con funciones globales.

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

1. Uso de la API de opciones

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

2. Usando el método de configuración

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

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

    console.log(this.$globalVariable)
</script>

Avatar de usuario de Teresa
teresa

Para aquellos de ustedes que están confundidos acerca de cómo acceder globalProperties en el setup() método, puede utilizar getCurrentInstance() como en la siguiente documentación.

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

  • De la documentación: “getCurrentInstance solo se expone para casos de uso avanzado, generalmente en bibliotecas. Se desaconseja encarecidamente el uso de getCurrentInstance en el código de la aplicación. NO lo use como una vía de escape para obtener el equivalente de esto en la API de composición”.

    – Coreo

    9 de noviembre de 2021 a las 13:18

Vista 3:

import { getCurrentInstance } from "vue";

const { proxy } = getCurrentInstance();

“proxy” contendrá el valor de globalProperties. Por ejemplo:

app.config.globalProperties.$toast = {...}

y luego:

proxy.$toast.success()

  • De la documentación: “getCurrentInstance solo se expone para casos de uso avanzado, generalmente en bibliotecas. Se desaconseja encarecidamente el uso de getCurrentInstance en el código de la aplicación. NO lo use como una vía de escape para obtener el equivalente de esto en la API de composición”.

    – Coreo

    9 de noviembre de 2021 a las 13:18

Avatar de usuario de Zach Jensz
Zach Jensz

En mi caso, tuve que crear una var global y obtener los datos de un script.
Se utiliza proporcionar e inyectar:

En 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')

En index.html:

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

En componente hijo:

    inject:['message'],
    mounted(){
    console.log(this.message)
  },

  • Es muy probable que su solución a veces se rompa con un error: TypeError: Cannot read properties of null (reading 'innerHTML'). En general, DOM se trata de DISPLAY, pero no de almacenamiento de datos. Entonces es más fácil escribir una variable para self y leer desde allí, aunque esto es malo por varias razones

    – Alejandro

    9 de marzo a las 8:41

¿Ha sido útil esta solución?