当前位置: 首页 > 知识库问答 >
问题:

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

尉迟明辉
2023-03-14

在我的Vue应用程序中,我有Vuex存储模块,它们的状态下有大量资源对象。为了方便地访问这些数组中的单个资源,我制作了Vuex getter函数,将资源或资源列表映射到各种键(例如“id”或“标签”)。这导致性能迟缓和巨大的内存占用。如何在没有如此多重复数据的情况下获得相同的功能和反应性?

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]]
        : []
    }
  }
}

共有3个答案

通奕
2023-03-14

虽然我同意@aidangarza,但我认为你最大的问题是反应性。特别是计算的属性。这增加了大量臃肿的逻辑和缓慢的代码,可以监听所有内容,而这是您不需要的。

找到相关的项目总是会让你在整个列表中循环-没有简单的方法。但是如果你自己说的话,速度会快得多。

我的意思是,计算属性是关于要计算的东西。你实际上是在过滤你的结果。在变量上放置一个观察者,然后自己调用获取者。类似的东西(半代码):

js prettyprint-override">watch: {
  itemId() {
    this.item = this.$store.getters['path/to/byId'][this.itemId]
  }
}

您可以首先使用项目进行测试,如果它工作得更好(我相信它会)-为更复杂的标签添加监视器。

祝你好运!

归建安
2023-03-14

虽然只存储选择字段是一个很好的中间选项(per@aidangarza),但当您最终得到真正庞大的数据集时,它仍然是不可行的。例如,积极处理“仅2个字段”的200万条记录仍然会消耗您的内存并破坏浏览器性能。

通常,在Vue中处理大型(或不可预测的)数据集时(使用VueX),只需完全跳过get和commithtml" target="_blank">机制。继续使用VueX来集中您的CRUD操作(通过操作),但不要尝试“缓存”结果,而是让每个组件在使用它的过程中缓存它们所需的内容(例如,结果的当前工作页、其中的一些投影等)。

根据我的经验,VueX缓存的目的是在当前使用环境(即当前登录的用户)中为合理有界的数据或有界的数据子集。当你有数据时,你不知道它的规模,然后只通过操作让你的Vue组件在“根据需要”的基础上访问它;这些潜在的巨大数据集没有获取器或突变。

罗昱
2023-03-14

要解决这个问题,请参考编程中一个古老的标准实践:索引。您可以在state.all中存储到项索引的映射,而不是在getter中存储具有完整项值的映射。然后,您可以创建一个新的getter,该getter返回一个函数来访问单个项目。根据我的经验,索引getter函数总是比旧getter函数运行得更快,它们的输出占用的内存空间也少得多(在我的html" target="_blank">应用程序中平均少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

 类似资料:
  • 我正在用Vue和Python构建一个基本的推特应用程序。我不确定在如何最好地构造表以及在哪里存储从应用编程接口返回的数据方面有什么最佳实践。 我有一张用户、推特和关注者/关注者的表格。从现在开始,登录会发出一个调用以获取用户信息,然后在成功登录后发出另一个HTTP调用以检索所有用户tweet。 我的表目前是这样设置的: 用户:id,用户名,密码,first_name,last_name 推文:id

  • 我有一个简单的应用程序与一个共同的堆栈: 后端服务器(Rails) 前端应用程序(Vue) 数据库(PG) Vue应用程序使用Vuex存储库的操作从后端获取数据,如下所示: 在组件的已创建生命周期挂钩中调用该操作,如下所示: 我上面写的代码中有一个问题,我实际上在模板中使用了计算值“participation”,如下所示: 当然,因为我在组件呈现自身时使用了参与,所以我从getter方法中得到了这

  • 我正在尝试修复VueJS SPA中出现的一种行为,其中出现了一种不稳定状态。应用程序不知道JWT已经过期,因此呈现出用户仍在登录的样子。例如,这可能发生在Hibernate之后。 这些用户可以继续向API发出任何请求,但最终会得到响应(这是正确的)。 我想要一个响应的全局处理程序。(这将是:从vuex清除所有与用户相关的内容,并将页面呈现为用户是访客,并弹出登录表单等。)否则,我将不得不为每个请求

  • 问题内容: 有一个包含两列的表:和。桌子上有关于。数据库是。 要求是开发一个连接到该数据库的简单Java EE应用程序,该应用程序允许用户通过遵循特定的URL 下载所有值。 如果我们将所有值组合成一个大块,然后将它们连接在一起(所有值之间用逗号分隔),然后将其发送给用户,这听起来是一个合适的解决方案吗? 该应用程序不是公开的,将由有限号使用。人。 问题答案: 最好的选择是 不要 以任何方式将数据存

  • 我有一个带post请求的控制器。我试图用一个简单的NotNull注释验证POJO。我正在使用ControllerAdvice来处理异常。 所以我尝试使用它,但当我启动应用程序时,我得到了以下信息: 因此,我想为BindException创建自己的处理程序,但当我为BindException类创建ExceptionHandler时,spring应用程序不会启动。如果我注释掉handleBindExc

  • 我有一个带有SSR、Vue Cli、Vuex和Typescript的Vue3项目。 在路由器页面中,我需要将数据提交到Vuex存储。在一个。vue文件我只是使用这个$在vuex中键入的存储。d、 例如: 但是如何从没有this或vue实例的ts文件(router/index.ts)中执行此操作呢。 我尝试导入存储索引文件并提交: 但我犯了个错误 类型“”上不存在属性“提交”()= 存储文件(因为我