【问题标题】:For each item in a Vuex Store, assign a score (based on a calculation), then sort all by score对于 Vuex Store 中的每个项目,分配一个分数(基于计算),然后按分数排序
【发布时间】:2019-07-29 14:45:36
【问题描述】:

我正在努力思考如何最好地将以下要求实现到 Vuex (vue.js) 应用程序中。

我会尽量保持简单,我希望实现的目标类似于 Hacker News 网站。因此,应用程序需要根据计算/算法计算每个项目(帖子)的分数。分数由喜欢和创建日期的组合决定。因此分数会不断更新(直到指定的时间段到期),因此分数不会存储在数据源中,而是由应用程序计算。

所以我的主要问题是,如何最好地为 Vuex 应用程序实现这一点?

我已经建立了一个 Vuex 帖子存储(我将每篇文章称为“帖子”),并且我能够在列表中显示所有帖子。所以现在我有两个主要目标:

  • 为帖子(文章)打分
  • 按分数过滤帖子结果列表。

我做了一些研究,一致认为最好将“分数”与“帖子”存储区分开(不添加到“帖子”数组中)。

以下代码运行良好,但感觉很冗长。将这些函数中的任何一个移动到“getters/mutations/actions”会更好吗?

请注意:对于这个例子,我已将计算/算法简化为“喜欢”总数加上“cmets”总数,显然最终算法更复杂,无法像黑客新闻一样工作。

<div>
  <button @click="postFilterKey = 'all'"><button>
  <button @click="postFilterKey = 'orderByScore'"><button>
</div>

<div v-for="post in filterPosts" v-bind:key="post.value">
  <p>Title: {{ post.title }}</p> 
  <p>Total Likes: {{ post.likes }}</p>
  <p>Total Comments: {{ post.comments }}</p>
  <p>Score: {{ post.comments | getScore(post.likes) }}</p>
</div>
computed: {
   ...mapState(["posts"]),
   filterPosts () {
     return this[this.postFilterKey]
   },
   all () {
     return this.posts;
   },
   orderByScore (){
     return this.posts.sort((b,a) =>
        this.calculateScore(a.totalComments, a.totalLike) - 
        this.calculateScore(b.totalComments, b.totalLike));
   },

methods: {
    calculateScore(totalComments, totalLikes) {
     let score = totalComments + totalLikes
     return score;
   },
}

filters: {
    getScore(totalComments, totalLikes) {
     let score = totalComments + totalLikes
     return score;
   },
}

感谢观看。

【问题讨论】:

  • 也许将orderByScore 移动到 Vuex Getter 中可以吗?然后订购的帖子直接链接到商店。如果你有工作代码,你的重构很大程度上取决于个人喜好。我个人会走“住在商店里有什么意义?”的OO路线。并将与商店联系最紧密的东西放在那里。任何过于依赖外部变量的东西都可能不适合住在商店里。再说一次,这只是我的偏好,您可能希望以不同的方式实现它。
  • 老实说,看看你的计算/方法/过滤器,作为 Getter 住在 Vuex 商店中,所有这些都是有意义的。
  • 此外,如果您需要多个组件中的逻辑,则将内容移入商店意味着您无需复制代码。

标签: vue.js vuejs2 vuex


【解决方案1】:

就像你说的,你所拥有的一切都可以正常工作,它本身并没有什么问题。

您当前的代码有几个问题可以改进:

  1. 如果您想在应用中不是该组件的直接子级的其他任何地方重复使用分数,则必须在该组件中复制 getScore() 函数,这更难维护。
  2. 每次呈现页面时,getScore() 函数都会为列表中的每个帖子重新运行一次,并且每次用户对列表进行排序时,calculateScore()getScore() 函数将重新运行一次列表中的每一项,效率不高。

正如您所提到的,一种解决方案是将这些函数作为吸气剂放在商店中。这将解决我上面列出的两个问题:

  1. 通过将这些函数保存在一个位置来保持代码干燥。
  2. 将这些函数作为 vuex getter 运行将缓存结果,以便它们仅在它们依赖的状态发生变化时重新运行。

您的商店中的 getter 属性可能如下所示:

getters: {
  postsWithScore: state => {
    return state.posts.map(post => {
      return {
        ...post,
        score: post.comments + post.likes,
    });
  }
}

查看 vuex 文档了解更多信息:https://vuex.vuejs.org/guide/getters.html

【讨论】:

  • 您的示例正是我想要的,现在感觉更干净(更干燥)!谢谢德文!
【解决方案2】:

我会考虑将分数计算转移到吸气剂。感觉就像是商业模式的一部分,为什么要把它固定在一个仅仅使用它的组件中呢?据我回忆,vuex 的 getter 内置了一些缓存,因此性能也有所提升。

附言。顺便说一句,基于时间的动态评分有其缺点。您可能不想在用户查看项目时移动项目,但是分页呢?当用户转到下一页并且您的分数同时发生变化时,列表的连续性就被打破了。无论如何,我相信这只是一种用户体验问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    相关资源
    最近更新 更多