如何重用应该使用唯一

如何重用应该使用唯一

本文介绍了如何重用应该使用唯一 vuex 存储实例的组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我认为文档的可重用模块是关键,但最后似乎不是为了这个目的,或者我不明白如何使用它.

父组件:(prop req-path" 用于传递不同的 URL 以使每个 FileExplorer 组件提交从 API 获取数据的操作,使用该 URL 路径)

<div class="容器"><FileExplorer req-path="/folder/subfolder"></FileExplorer><FileExplorer req-path="/anotherfolder"></FileExplorer>

</模板><脚本>import { mapState, mapGetters } from "vuex";从@/components/FileExplorer.vue"导入文件资源管理器;导出默认{成分: {文件管理器}};

可重用组件:

<div class="容器"><ul v-for="(item, index) in folderIndex" :key="index"><li>结果:{{ item.name }}</li>

</模板><脚本>import { mapState, mapGetters } from "vuex";导出默认{道具:[reqPath"],},计算:{...mapState("fileExplorer", ["folderIndex"])},创建(){//从 API 中获取数据this.$store.dispatch("fileExplorer/indexingData", {reqPath: this.reqPath}).catch(错误=> {console.log("发生错误:", error);this.errors = error.response.data.data;});}};

store.js 我在其中调用我在不同文件中分开的 store 模块,这里只有 fileExplorer 模块让我们感兴趣.为了清晰起见,我简化了文件,但我有一些其他状态和许多变化.

从'vue'导入Vue从 'vuex' 导入 Vuex//导入模块从@/store/modules/fileExplorer"导入 {fileExplorer}Vue.use(Vuex)导出默认新 Vuex.Store({模块:{文件管理器,…}})

@/store/modules/fileExplorer.js

从@/utils/ApiService"导入ApiService导出 const fileExplorer = ({命名空间:真,状态: {文件夹索引:{},},突变:{//从操作 (indexingData) 调用以从 API 获取文件夹/文件结构SET_FOLDERS_INDEX(状态,数据){state.folderIndex = data.indexingData},动作:{//使用 req-path 作为 url 从 API 获取数据索引数据({犯罪}, 请求路径) {返回 ApiService.indexingData(reqPath).then((响应) => {commit('SET_FOLDERS_INDEX', response.data);}).catch((错误) => {console.log('出现错误:', error.response);});}}});

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

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

解决方案

当你从同一个模块配置创建多个模块时,模块重用是关于.

首先,使用函数来声明模块状态而不是普通对象.

如果我们使用普通对象来声明模块的状态,那么状态对象将通过引用共享并导致跨存储/模块变异时说明污染.

const fileExplorer = {状态 () {返回 {文件夹索引:{}}},//突变、动作、吸气剂...}

然后,每次新FileExplorer注册一个新模块/code> 组件被创建并在组件被销毁之前取消注册该模块.

<div class="容器"><ul v-for="(item, index) in folderIndex" :key="index"><li>结果:{{ item.name }}</li>

</模板><脚本>import { fileExplorer } from "@/store/modules/fileExplorer";从@/store/index"导入商店;变量 uid = 1导出默认{道具:[reqPath"],数据() {返回 {命名空间:`fileExplorer${uid++}`}},计算:{文件夹索引(){返回 this.$store.state[this.namespace].folderIndex}},创建(){//动态注册新模块store.registerModule(this.namespace, fileExplorer);//从 API 中获取数据this.$store.dispatch(`${this.namespace}/indexingData`, {reqPath: this.reqPath}).catch(错误=> {console.log("发生错误:", error);this.errors = error.response.data.data;});},beforeDestroy() {//注销动态创建的模块store.unregisterModule(this.namespace);}};

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

export default new Vuex.Store({模块:{//fileExplorer, <-- 移除这个静态模块}})

I try to find a way to use vuex with reusable component which store data in a store. The thing is, I need the store to be unique for each component instance.

I thought Reusable module of the doc was the key but finally it doesn't seem to be for this purpose, or i didn't understand how to use it.

The parent component:(the prop "req-path" is used to pass different URL to make each FileExplorer component commit the action of fetching data from an API, with that url path)

<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>

The reusable component:

<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 where I invoke my store module that I separate in different files, here only fileExplorer module interest us.EDIT : I simplified the file for clarity purpose but I have some other state and many mutations inside.

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);
        });
    }
  }
});

I need each component to show different data from those 2 different URL, instead i get the same data in the 2 component instance (not surprising though).

Thanks a lot for any of those who read all that !

解决方案

Module reuse is about when you are creating multiple modules from the same module config.


First, use a function for declaring module state instead of a plain object.

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

Then, dynamically register a new module each time a new FileExplorer component is created and unregister that module before the component is destroyed.

<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>

You no longer need the static module registration declared at store creation.

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

这篇关于如何重用应该使用唯一 vuex 存储实例的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 20:33