如何在Vuex中访问Vue实例

21

我在Vue.js项目的main.js中声明了一个全局变量。

Vue.prototype.$API = "myapihere"

我希望能够在任何地方使用它,并且通过 this.$API 正常工作。

但是在 Vuex 中它无法正常工作。

console.log(this.$API);

这里this.$API未定义的

我如何在Vuex中使用我的$API


1
在 Vuex 中,this 不是指 Vue 实例,所以它无法正常工作,请尝试使用 this._vm - Chris Li
如果您的操作、获取器等在不同的文件中,则此方法无法正常工作。 - secondman
@VinceKronlein,这个问题已经得到解答了。 - Rohit Nishad
是的,但这不正确。当从文件导入操作、突变等时,这些文件无法访问 this._vm,在我的 actions.js 文件中,this 是未定义的。 - secondman
@VinceKronlein 或许吧...我不确定,我正在为一个逻辑组件编写一个单独的文件,在那个文件中,我包含了该组件的所有内容(操作、状态、突变等)。 - Rohit Nishad
@RohitNishad 是的,这种情况下 this 将指向你的 mutations 或 actions 所在的 Vuex.Store 实例。但是在真实世界的应用中,这并不是一个常见的场景。当你在一个文件中有 200 个 actions 和 mutations 时,你的代码将会变得混乱且难以维护。因此,在最简单的应用程序中,这将起作用,但在一个相当大的应用程序中则不然。 - secondman
5个回答

21

Vue 2和Vuex 3解答

在store中,通过访问this._vm可以访问Vue实例

const store = new Vuex.Store({
  mutations: {
    test(state) {
      console.log(this._vm);
    }
  }
});

4
请注意,在Vue 3兼容的Vuex 4中,此方法不起作用。即使在Vuex 3中,它也不是公共API的一部分。使用未记录的函数/属性将成为未来问题的原因... - Michal Levý
1
这个方法有一些限制。_vm无法访问其他插件,因为它指的是VueX用于存储的内部、独立的Vue实例。例如,如果您使用vuetify,则无法在此_vm上使用它,也无法使用路由器。只能进行原型修改。 相反,我使用了一个IIFE,在其中定义了const app = new Vue(/* settings */); store:$app = app,以便在存储初始化自己之后,提供自己的Vue实例引用来渲染我的应用程序。然后通过this.$app从存储中访问根实例。 - Excalibaard

13
我正在使用Vue 3,发现Vue.prototype.$foo在此版本中已被删除。我还发现,在我的VueX版本中没有this._vm
我研究了 Vue 3 文档中推荐的 Provide / Inject 方法,它能够很好地访问组件内的全局变量,但我无法从 store 中访问它们。
我选择了在挂载应用程序之前,在 Vue 对象上使用 globalProperties 以及在store上使用标准属性来设置它们。 main.js:
import store from './store/index';
import App from './App.vue';

// Load custom globals
import conf from '@/inc/myapp.config';

const app = createApp(App)
  .use(store);

// Register globals in app and store
app.config.globalProperties.$conf = conf;
store.$conf = conf;

app.mount('#app');
我喜欢的是,我可以在store和组件中以相同方式访问全局变量。 在组件中:
export default {
  data() {
    return {
    };
  },
  created() {
    console.log( this.$conf.API_URL );
  },
}

...你可以通过相同的方式从actions、mutations和getters访问this.$conf.API_URL

一旦我找到了这个解决方案,我就不再需要从存储中访问整个Vue实例,但如果出于某些原因需要访问它,可以在main.js中的相同位置分配store.$app = app


我在Vue 2文档中没有看到任何有关globalProperties的提及,因此您需要阅读一些相关内容并进行实验,但我想原则仍然适用。我很想知道您的进展如何。 - Vilāsamuni
只有在 JavaScript 中才能运行,TypeScript 无法实现。 - CalibanAngel
这对我帮助很大!!!非常好用。基本上,无论您在哪里定义全局变量,都像这个用户一样将它们分配给vue和router。 - user6269972

3
您有两种方法:
  1. Pass down the property (or even access the _vm property from inside Vuex) as an argument from a component

    methods: {
      this.$store.dispatch('someAction', this.$API)
    }
    
  2. Declare and export that same variable from another file and consume it from your main.js AND your Vuex file:

    // api.js
    export const API = "http://localhost:5000/api"
    
    // main.js
    import { API } from './api.js
    ...
    Vue.prototype.$API = API
    
    // store.js
    import { API } from './api.js
    
    // you can use API now!
    
虽然我个人更倾向于第二种方式,但我不会在Vue中存储API路径,而是将api.js文件作为服务执行所有Ajax调用,并从需要的位置使用该文件。

2

使用this._vm

这是为什么

默认情况下,当您在vuex store中访问this时,它将指向store,因此它会输出类似于这样的内容

enter image description here

所以在此之后,您会看到存储中有一个名为_vm的东西,如下所示 enter image description here

因此,_vm指向vue组件,因此要访问它,您需要使用this._vue

您可以更好地创建vue实例的getter

const store = new Vuex.Store({
  getters: {
    vue(state) {
      return this._vm
    }
  }
});

//so you can use it across your store
store.getters.vue

//Note
//the above way of accessing getter works on non `namespaced` stores 

0
最近,在 Vuex 4.* 和 Vue 3.* 中,store 对象中未定义 this.$app。相反,你可以使用 Vue Router 定义的 this.$router
因此,在 JavaScript 中,获取 store 中的 app 的方法如下:
现在的代码应该是:router.app = app;,在 action 中,例如:let app = this.$router.app;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接