1

With Vue 3 Composition API, each view needs to have these:

import { useRouter, useRoute } from 'vue-router'
import { useStore } from 'vuex'


export default {
    setup() {
        const router = useRouter()
        const store = useStore()

        // ...
     }
}

Is there a way to declare these somehow just once, pass them to the created app, and simply use them without these declarations inside the app views? With vue2, these were passed when app was initialized, then this.$store / this.$router simply worked.

An idea with global vars, which can easily cause issues: in app.vue, these could be declared once like this:

import { useStore } from 'vuex'

export default {
    setup() {
        globalthis.store = useStore()

then store would work everywhere.

tony19
  • 125,647
  • 18
  • 229
  • 307
Marius
  • 1,659
  • 3
  • 22
  • 31
  • 1
    *then store would work everywhere* - welcome to oldschool JS. This is how it was done previously, and the code was horrible. *Would there be any downsides?* - then an author of some library in use with the same mindset thinks it's a good idea to create `store` global variable, and it becomes a mess. Polluting global scope is a bad practice. I hope somebody can link to a question that explains in detail why it's so. It's not specific to Vue. Polluting `Vue.prototype` in Vue 2 is in the same boat. – Estus Flask Jul 31 '21 at 18:32
  • You can try to create another composition API to return a new scoped store and router. I also have the same idea as @Estus Flask, scoped codes can make it easy to debug. global value sometimes you difficult to know when it has been changed by some codes when you have to maintain multiple components. – Chunbin Li Aug 01 '21 at 02:20
  • Agree that globals can cause issues. Is there a way with vue 3 to pass these to the created app and have them available only inside app views, similar to how vue2 worked? – Marius Aug 01 '21 at 06:57

1 Answers1

1

The component instance is not available in setup() because the component has not been created yet, so there's no this context in the Composition API to use this.$store.

I believe the only way to make the store/router variables available in setup() without any other imports is to attach them to window/globalThis as globals (ignoring the caveats of globals):

// router.js
import { createRouter } from 'vue-router'
export default createRouter({/*...*/})

// store.js
import { createStore } from 'vuex'
export default createStore({/*...*/})

// main.js
import router from './router'
import store from './store'

window.$router = router
window.$store = store

Note the store and router are still available in the Options API and within the template as $store and $router, respectively, with Vuex 4 and Vue Router 4:

<template>
  <div>{{ $store.state.myProp }}</div>
  <button @click="$router.back()">Back</button>
</template>

<script>
export default {
  mounted() {
    console.log(this.$store.state.myProp)
    console.log(this.$router.currentRoute)
  }
}
</script>
tony19
  • 125,647
  • 18
  • 229
  • 307