如何重用应使用唯一vuex存储实例的组件

时间:2019-11-05 20:44:25

标签: vue.js vuejs2 vue-component vuex vuex-modules

我试图找到一种将vuex与可重用组件一起使用的方法,该组件将数据存储在商店中。问题是,我需要每个组件实例的存储都唯一。

我以为文档的可重用模块是关键,但最终似乎不是出于这个目的,或者我不知道如何使用它。

父组件: (道具“ req-path”用于传递不同的URL,以使每个FileExplorer组件都可以使用该URL路径来执行从API提取数据的操作)

<template>
  <div class="container">
    <FileExplorer req-path="/folder/subfolder"></FileExplorer>
    <FileExplorer req-path="/anotherfolder"></FileExplorer>
  </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";
import FileExplorer from "@/components/FileExplorer.vue";

export default {
  components: {
    FileExplorer
  }
};
</script>

可重用组件:

<template>
 <div class="container">
      <ul v-for="(item, index) in folderIndex" :key="index">
        <li>Results: {{ item.name }}</li>
      </ul>
    </div>
 </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";

export default {
  props: ["reqPath"],
  },
  computed: {
    ...mapState("fileExplorer", ["folderIndex"])
  },
  created() {
    // FETCH DATA FROM API
    this.$store
      .dispatch("fileExplorer/indexingData", {
        reqPath: this.reqPath
      })
      .catch(error => {
        console.log("An error occurred:", error);
        this.errors = error.response.data.data;
      });
  }
};
</script>

store.js,在这里我调用在不同文件中分离的商店模块,这里只有fileExplorer模块使我们感兴趣。 编辑:为了清晰起见,我简化了文件,但我还有其他一些状态,并且内部有许多突变。

import Vue from 'vue'
import Vuex from 'vuex'

// Import modules
import { fileExplorer } from '@/store/modules/fileExplorer'

Vue.use(Vuex)

export default new Vuex.Store({
modules: {
    fileExplorer,
…
  }
})

@ / store / modules / fileExplorer.js

import ApiService from "@/utils/ApiService"

export const fileExplorer = ({
namespaced: true,

  state: {
    folderIndex: {},
},

  mutations: {
    // Called from action (indexingData) to fetch folder/fil structure from API
    SET_FOLDERS_INDEX(state, data) {
      state.folderIndex = data.indexingData
},

actions: {
    // Fetch data from API using req-path as url 
    indexingData({
      commit
    }, reqPath) {
      return ApiService.indexingData(reqPath)
        .then((response) => {
          commit('SET_FOLDERS_INDEX', response.data);
        })
        .catch((error) => {
          console.log('There was an error:', error.response);
        });
    }
  }
});

我需要每个组件显示来自这2个不同URL的不同数据,相反,我在2个组件实例中获得相同的数据(虽然并不奇怪)。

非常感谢那些阅读所有这些内容的人!

1 个答案:

答案 0 :(得分:0)

模块重用是关于在同一模块配置中创建多个模块时的情况。


首先,使用声明模块状态的函数代替普通对象。

  

如果我们使用一个普通的对象来声明模块的状态,那么   状态对象将被引用共享,并导致交叉存储/模块   变异时会造成污染。

const fileExplorer = {
  state () {
    return {
      folderIndex: {}
    }
  },
  // mutations, actions, getters...
}

然后,每次创建新的FileExplorer组件时动态地register a new module,并且在销毁该组件之前unregister that module动态地enter image description here

<template>
 <div class="container">
      <ul v-for="(item, index) in folderIndex" :key="index">
        <li>Results: {{ item.name }}</li>
      </ul>
    </div>
 </div>
</template>

<script>
import { fileExplorer } from "@/store/modules/fileExplorer";
import store from "@/store/index";

var uid = 1

export default {
  props: ["reqPath"],
  data() {
    return {
      namespace: `fileExplorer${uid++}`
    }
  },
  computed: {
    folderIndex() {
      return this.$store.state[this.namespace].folderIndex
    }
  },
  created() {
    // Register the new module dynamically
    store.registerModule(this.namespace, fileExplorer);

    // FETCH DATA FROM API
    this.$store
      .dispatch(`${this.namespace}/indexingData`, {
        reqPath: this.reqPath
      })
      .catch(error => {
        console.log("An error occurred:", error);
        this.errors = error.response.data.data;
      });
  },
  beforeDestroy() {
    // Unregister the dynamically created module
    store.unregisterModule(this.namespace);
  }
};
</script>

您不再需要在商店创建时声明的静态模块注册。

export default new Vuex.Store({
  modules: {
    // fileExplorer, <-- Remove this static module
  }
})