javascript - 使用 Vuex 在 Vue 应用程序中高效地处理大型数据集

标签 javascript vue.js vuejs2 vuex

在我的 Vue 应用程序中,我有 Vuex 存储模块,其状态中包含大量资源对象。为了轻松访问这些数组中的单个资源,我制作了 Vuex getter 函数,将资源或资源列表映射到各种键(例如“id”或“tags”)。这导致性能低下和巨大的内存内存占用。如何在没有这么多重复数据的情况下获得相同的功能和 react 性?

商店模块示例

export default {
  state: () => ({
    all: [
      { id: 1, tags: ['tag1', 'tag2'] },
      ...
    ],
    ...
  }),

  ...

  getters: {
    byId: (state) => {
      return state.all.reduce((map, item) => {
        map[item.id] = item
        return map
      }, {})
    },

    byTag: (state) => {
      return state.all.reduce((map, item, index) => {
        for (let i = 0; i < item.tags.length; i++) {
          map[item.tags[i]] = map[item.tags[i]] || []
          map[item.tags[i]].push(item)
        }
        return map
      }, {})
    },
  }
}

组件示例

export default {
  ...,

  data () {
    return {
      itemId: 1
    }
  },

  computed: {
    item () {
      return this.$store.getters['path/to/byId'][this.itemId]
    },

    relatedItems () {
      return this.item && this.item.tags.length
        ? this.$store.getters['path/to/byTag'][this.item.tags[0]]
        : []
    }
  }
}

最佳答案

要解决此问题,请引用编程中一种古老的标准做法:索引。您可以将映射存储到 state.all 中的项目索引,而不是在 getter 中存储一个包含完整项目值的映射。然后,您可以创建一个新的 getter,它返回一个函数来访问单个项目。根据我的经验,索引 getter 函数总是比旧的 getter 函数运行得更快,而且它们的输出占用的内存空间要少得多(在我的应用程序中平均减少 80%)。

新商店模块示例

export default {
  state: () => ({
    all: [
      { id: 1, tags: ['tag1', 'tag2'] },
      ...
    ],
    ...
  }),

  ...

  getters: {
    indexById: (state) => {
      return state.all.reduce((map, item, index) => {
        // Store the `index` instead of the `item`
        map[item.id] = index
        return map
      }, {})
    },

    byId: (state, getters) => (id) => {
      return state.all[getters.indexById[id]]
    },

    indexByTags: (state) => {
      return state.all.reduce((map, item, index) => {
        for (let i = 0; i < item.tags.length; i++) {
          map[item.tags[i]] = map[item.tags[i]] || []
          // Again, store the `index` not the `item`
          map[item.tags[i]].push(index)
        }
        return map
      }, {})
    },

    byTag: (state, getters) => (tag) => {
      return (getters.indexByTags[tag] || []).map(index => state.all[index])
    }
  }
}

新组件示例

export default {
  ...,

  data () {
    return {
      itemId: 1
    }
  },

  computed: {
    item () {
      return this.$store.getters['path/to/byId'](this.itemId)
    },

    relatedItems () {
      return this.item && this.item.tags.length
        ? this.$store.getters['path/to/byTag'](this.item.tags[0])
        : []
    }
  }
}

变化看似很小,但在性能和内存效率方面却产生了巨大的差异。它仍然是完全响应式的,就像以前一样,但您不再复制内存中的所有资源对象。在我的实现中,我抽象出了各种索引方法和索引扩展方法,使代码非常易于维护。

您可以在 github 上查看完整的概念证明,此处:https://github.com/aidangarza/vuex-indexed-getters

关于javascript - 使用 Vuex 在 Vue 应用程序中高效地处理大型数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52671666/

相关文章:

javascript - 构建命运之轮游戏,我试图获取按键事件来检测随机单词数组中的字母

javascript - 如何在 Service Worker 中编辑请求 url?

vue.js - 如何使用 v-bind 对象在子组件中获取 Prop

javascript - 为 Vue Select2 包装器组件使用动态 AJAX URL

javascript - 处理 ajax 和生成超出原型(prototype)设计的 html 的最佳方法是什么

javascript - 尝试使用 axios 和 formData 发布数据,但它是空的

jquery - vuejs : recommended way to use a jquery plugin

javascript - Lodash 多键与多个值数组过滤器

node.js - Vuejs错误: Rule can only have one resource source (provided resource and test + include + exclude)

javascript - 如何在动态生成的 Rails 表上创建 JS 函数