【问题标题】:Using parameters for computed functions in Vue在 Vue 中使用计算函数的参数
【发布时间】:2020-04-27 10:10:44
【问题描述】:

我很难为计算不足的函数使用参数。对于这个例子,我有一个对象数组,每个对象都是一个游戏(棋盘游戏、视频游戏等)。我想显示我数组中游戏的一些统计数据,例如玩的总游戏、玩的总小时数、视频游戏的游戏数量、所有游戏的总价格、平均游戏评分等。

我的每个统计信息的模板如下所示:

<div class="game-stat">
    <p>{{ gamesPlayedCounter }}/{{ games.length }}</p>
</div>

然后在我的计算中我会有一个类似的函数:

gamesPlayedCounter:function(){
   var result = gameList.reduce((res, item) => item.status == 'played' ? res + 1 : res, 0);
   return result;
}

问题是,我的很多统计数据都遵循同样的模式。如果我想计算电子游戏的数量,我可以这样做:

gamesTypeCounter:function(){
  var result = gameList.reduce((res, item) => item.type == 'video-game' ? res + 1 : res, 0);
  return result;
}

因此,这给了我所有具有视频游戏类型的游戏的总数。我最终得到了其中的 10 个,用于不同的统计数据。我知道我应该只用一个函数就能做到这一点并传入参数。

我认为我可以添加参数并将 item.type 切换为我想要检查的内容,然后将 'video-game' 切换为我想要检查的值,但这不起作用。这是我尝试过的:

<div class="game-stat">
    <h4>Total Games Played:</h4>                    
    <p>{{ counter('type', 'video-game') }}/{{ games.length }}</p>
</div>

counter:function(key, value){
   var result = gameList.reduce((res, item) => item.key == value ? res + 1 : res, 0);
   return result;
}

这不起作用,所以现在我不确定如何创建一个在 Vue 中给定特定键和值时计数的函数。我什至应该为此使用计算吗?任何见解将不胜感激!

【问题讨论】:

  • 这能回答你的问题吗? Dynamically access object property using variable。使用item[key] 而不是item.key,这与item["key"] 相同——这与Vue 无关。另一种解决方案是简单地将一个循环中所有键的值相加。或gameList.filter(e =&gt; e[key] === value).length.

标签: javascript vue.js


【解决方案1】:

您不能将computed 与参数一起使用(好吧,从技术上讲,您可以使用“hack”从computed 属性返回新函数,但它就像普通的method 一样工作......只是肮脏和混乱)。使用 David 建议的方法确实有效,但方法实际上并不有效,因为每次重新渲染模板时都会调用它们,并且您希望使您的应用程序尽可能快速和有效,对吧?

这样做:

<template>
  <ul>
    <li>Total games played: {{ gamesStats.totalGames }}</li>
    <li>Total video games: {{ gamesStats.videoGames }}</li>
  </ul>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      gameList: [
        { name: "doom", type: "video", isPlayed: true },
        { name: "chess", type: "board", isPlayed: true },
        { name: "checkers", type: "board", isPlayed: false },
        { name: "fortnite", type: "video", isPlayed: true }
      ],
      stats: {
        totalGames: item => (item.isPlayed ? 1 : 0),
        videoGames: item => (item.type === "video" ? 1 : 0)
      }
    };
  },
  computed: {
    gamesStats() {
      const entries = Object.entries(this.stats);

      // initialise aggregator with zeroes...
      const aggregator = {};
      entries.forEach(([key, func]) => (aggregator[key] = 0));

      this.gameList.reduce(function(acc, item) {
        entries.forEach(function([key, func]) {
          acc[key] += func(item);
        });
        return acc;
      }, aggregator);

      return aggregator;
    }
  }
};
</script>

现在您的 gamesStats 仅在 gameList 数组发生变化时重新计算(不是在每次重新渲染时),您可以做更多有趣的事情,而不仅仅是将对象键与某个固定值进行比较。

另外,你有一个漂亮干净的模板,没有不必要的 JS 代码..

【讨论】:

    【解决方案2】:

    你可以用一个方法来做到这一点。这是一个例子:

    <template>
      <ul>
        <li>Total games played: {{ countWhere('isPlayed', true) }}</li>
        <li>Total video games: {{ countWhere('type', 'video') }}</li>
      </ul>
    </template>
    
    export default {
      data() {
        return {
          gameList: [
            { name: 'doom', type: 'video', isPlayed: true },
            { name: 'chess', type: 'board', isPlayed: true },
            { name: 'checkers', type: 'board', isPlayed: false },
            { name: 'fortnite', type: 'video', isPlayed: true },
          ],
        };
      },
      methods: {
        countWhere(key, value) {
          return this.gameList.filter(game => game[key] === value).length;
        },
      },
    };
    

    【讨论】:

      猜你喜欢
      • 2018-05-11
      • 2018-03-23
      • 2015-08-29
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多