Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to encapsulate Vuex store inside Vue plugin (its install function)?

  • I have a plugin and this plugin uses Vuex
// plugin.js
import Vuex from "vuex";
import store from "./store.js";

export default {
  install(Vue, options) {
    const storeInstance = new Vuex.Store(store);
    Vue.prototype.$store = storeInstance;
  }
};
  • And in that plugin I import a store object.
// store.js
export default {
  actions: {
    SOME_RANDOM_ACTION({ state, commit }) {
      console.log("some random action");
    }
  }
};

Dispatching actions and using state is fine and works as expected.

But when I add this plugin to another Vue instance that uses vuex, store object re-initializes with new state.

// index.js
import Vue from "vue";
import Vuex from "vuex";
import App from "./App.vue";
import plugin from "./plugin.js";

Vue.use(Vuex);
Vue.use(plugin);

new Vue({
  // WARN when i uncomment this next line of code Vuex gets re-initialized with new object
  // store: new Vuex.Store({ state: { hello: "hix" } }),
  components: {
    App
  }
}).$mount("#app");

When you uncomment store initialization, store that was defined in the plugin is now not available.

Currently, I have these solutions in mind:

  1. Export my plugin store object to index.js main app, and use this store as a module.
  2. Use some other state management.

Is there a way to use Vuex inside my plugin?

https://codesandbox.io/s/vibrant-sanne-67yej?file=/src/main.js:0-371

like image 218
ColdHands Avatar asked Aug 31 '25 01:08

ColdHands


1 Answers

Vuex plugin uses store option to assign store instance to Vue.prototype.$store, similarly to your own plugin.

If the intention is to use multiple stores, their names shouldn't collide. The key is to name your store object inside plugin something other than $store

Vue.prototype.$myPluginStore = storeInstance;

But this still doesn't encapsulate $myPluginStore inside the plugin, as it is accessible within the app.

// App.vue

computed: {
    appState() {
      return this.$store.state;
    },
    pluginState() {
      return this.$myPluginStore.state; // this is now accessible within the main app
    }
}

It would be a reasonable solution to allow a store to be used as a module of existing store instead of creating a new store, but only when used within one app and not when used as a plugin for a package.

The main problem is that default store instance ($store) can make use of Vuex helpers - mapGetters, etc.

like image 193
Estus Flask Avatar answered Sep 02 '25 14:09

Estus Flask