有没有办法将 Vuex 存储封装在 Vue 插件(其安装功能)中?

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

// 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;
  }
};
// store.js
export default {
  actions: {
    SOME_RANDOM_ACTION({ state, commit }) {
      console.log("some random action");
    }
  }
};

调度操作和使用状态都很好并且按预期工作。

但是当我将此插件添加到另一个使用 vuex 的 Vue 实例时,存储对象会重新初始化为新状态。

// 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");

当您取消注释商店初始化时,插件中定义的商店现在不可用。

目前,我想到了这些解决方案:

  1. 将我的插件商店对象导出到 index.js 主应用程序,并将此商店用作模块。
  2. 使用一些其他的状态管理。

有没有办法在我的插件中使用 Vuex?

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

Vuex 插件使用 store 选项将存储实例分配给 Vue.prototype.$store,类似于您自己的插件。

如果打算使用多个商店,它们的名称不应冲突。关键是将插件中的商店对象命名为 $store

以外的名称
Vue.prototype.$myPluginStore = storeInstance;

但这仍然没有将 $myPluginStore 封装在插件中,因为它可以在应用程序中访问。

// App.vue

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

允许将商店用作现有商店的模块而不是创建新商店是一个合理的解决方案,但仅限于在一个应用程序中使用而不是用作包的插件时。

主要问题是默认商店实例 ($store) 可以使用 Vuex 助手 - mapGetters

您可以利用插件公开的安装方法来访问商店 - 这应该可以从您的其他组件访问。

一种可能的解决方案是在 index.js 中注册您的商店,例如:

import Vue from "vue";
import App from "./App.vue";
import store from "./store";
import plugin from "./plugin";

Vue.use(plugin);

new Vue({
  store,
  components: {
    App
  }
}).$mount("#app");

然后您可以公开 $doStuff() 并在 plugin.js

中访问 $store
export default {
  install(Vue) {
    Vue.prototype.$doStuff = function (payload) {
      this.$store.dispatch("SOME_RANDOM_ACTION", payload);
    };
  }
};

可以从您的插件或所有其他组件访问商店实例。

你可以看到一个working sample here