twtjudy1128
@twtjudy1128 (Juri Tawata)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Vue.jsで配列内の金額を合計したい

やりたいこと

Vue.jsでアプリを作っています。
script部分で、dataのmenusをランダムにシャッフルして、HTML部分に4つ抽出して表示させています。

その抽出された4つのmenuのpriceを合計して表示させたいのが、今回の目的です。

現状のコードとエラー内容

今書けているのが以下のコードです。
totalpriceが、抽出された4つのmenuではなく、また別にランダムで抽出された別menuの合計priceになってしまっていて困っています。

どのようにすれば、該当の4つの合計を表示させられますでしょうか?
お知恵をお借りいただけますと幸いです。

 <li class="list-group-item list-group-item-light" v-for="i in 4">
            {{menus[i].name}} ・・・{{menus[i].price}}円(税別)
 </li>
 <li class="list-group-item list-group-item-success">
            合計金額は<b>{{totalprice}}</b>円(税別)です!
 </li>
      <script>
        const app = new Vue({
            el: '#app',
            data: {
                show: false,
                menus: [
                    { name: "チキンカレー", price: 650 },
                    { name: "マトンカレー", price: 850 },
                    { name: "ダル", price: 600 },
                    { name: "グンドゥルック・コ・ジョル", price: 700 },
               //数が多いので省略
                    { name: "マネロティ", price: 500 },
                    { name: "ライス", price: 280 },
                ]
            },
            methods: {
                gacha: function() {
                    this.menus.sort(() => Math.random() - 0.5);
                    this.show = true;                       
                },
            },
            computed: {
                totalprice: function() {
                    let total = 0;
                    for(let i=0; i<=3; i++) {
                        total += this.menus[i].price;
                    }
                return total;
                },
            }

        })    

      </script> 
0

2Answer

<li class="list-group-item list-group-item-light" v-for="i in 4">

この v-for="i in 4"i の元になる配列は [0,1,2,3] ではなく [1,2,3,4] ですね。
なので、リストと合計金額が別のランダムメニューが基になっているわけではなく、拾っているインデックスが違っています。

1Like

Comments

  1. computed で最初の4メニューを取り出した配列を返すようにして、 v-for でもその配列を利用するようにしたほうがいいと思います。
    合計金額もその配列を基に計算するようにすると齟齬が起きないです。
  2. @twtjudy1128

    Questioner

    ご回答いただき、本当にありがとうございます!

    for(let i=0; i<=3; i++) {
    total += this.menus[i].price;

    ここが間違っていたのですね!
    iの初期値を1にして、

    for(let i=1; i<=4; i++) {

    に修正したら、合計金額がうまく合いました!

    感謝です!

  3. その形だと、「最初の4個」ではなく「2個目から5個目」を取り出してますので、(今回はそもそもランダムなので問題ないですが) 意図とは違う結果になっているはずです。
    テンプレートの方で、アクセスするインデックスを「i」ではなく「i-1」にして帳尻を合わせたほうが良いでしょう。

    また、そもそもの流れとして、この方法だと、例えばメニュー表示数を5個に変更する場合にも修正箇所が2箇所あり、位置的にも離れているのがつらいです。
    4メニューを取り出すcomputedを作ったほうがわかりやすいと思います。
  4. @twtjudy1128

    Questioner

    ご丁寧にありがとうございます><

    今回はどうにか形にはなってるけど、少し仕様を変えるってなった場合にガタが出ちゃう感じですね。とても勉強になります。

    まだまだ理解するのがやっとですが、使いこなせるように試してみます!
    ありがとうございます!

以下のように totalprice とテンプレートが同じ partOfMenus を参照している形のほうがよいでしょう。
また、表示数を変えたいときは data.displayLength を変えるだけになります。

<li v-for="menu in partOfMenus" :key="menu.name">
            {{ menu.name }} ・・・{{ menu.price }}円(税別)
 </li>
<li>
            合計金額は<b>{{ totalprice }}</b>円(税別)です!
 </li>
<script>
// el, methodsは変更ないので略
const app = new Vue({
  data: {
    menus: [
    //略
    ],
    displayLength: 4,
  },
  computed: {
    partOfMenus: function() {
      return this.menus.slice(0, this.displayLength)
    },
    totalprice: function() {
      let total = 0
      const length = this.partOfMenus.length
      for (let i = 0; i < length; i++) {
        total += this.menus[i].price
      }
      return total
    },
  },
})
</script>
  • totalpriceArray.reduce() を使えるようになるといいと思います。
1Like

Comments

  1. @twtjudy1128

    Questioner

    補足もいただき、本当にありがとうございます><

    今回スクールの宿題でアプリ作成にチャレンジしてるのですが、締め切りが今日なので、せっかく回答いただいたのに反映できないまま、このあとQiita記事書いちゃうんですけど、見なかったふりしていただけると幸いです。笑

    ただ、教えていただいたスマートなコードを自分のものにしたいので、試して理解してみます!ありがとうございます!

Your answer might help someone💌