質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Q&A

0回答

726閲覧

買い物かごから購入をキャンセルする場合の処理の正しい書き方

FKM

総合スコア3647

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

0グッド

0クリップ

投稿2021/10/13 05:34

Vuexを本格的に学習しようとして、以下のページを参照しながら買い物かごの制御を作ってみました。
shopping-cart
【vue.js】ショッピングカートを作ってVuexを理解

このページも説明不足なところがありそのままでは動かず、原本や他のVuexの学習用記事なども参考にしながら知識を補っていき一旦は動く形にしたので、更に発展的学習のため、買い物のキャンセル機能を導入してみました。

なお、使用Vue及び記法はVue2.xです。

txt

1任意のプロジェクト 2 - src 3 - components 4 ProductList.vue //子コンポーネント(商品一覧部分) 5 Shop.vue //親コンポーネント 6 ShoppingCart.vue //子コンポーネント(買い物かご部分) 7 - store 8 index.js

shop.vue

vue

1<template> 2 <div> 3 <h1>Shopping Cart Example</h1> 4 <hr> 5 <h2>商品一覧</h2> 6 <ProductList/><!-- 商品一覧のコンポーネント --> 7 <hr> 8 <ShoppingCart/><!-- 買い物かごのコンポーネント --> 9 </div> 10</template> 11<script> 12import ProductList from './ProductList.vue' 13import ShoppingCart from './ShoppingCart.vue' 14 15export default { 16 components: { ProductList,ShoppingCart } 17} 18</script>

productList.vue

vue

1<template> 2 <ul> 3 <li v-for="product in products" :key="product.id"> 4 {{ product.title }} - {{ product.price }} 5 <button 6 @click="addProductToCart(product)" 7 :disabled="!product.inventory" 8 >かごに入れる</button> 9 </li> 10 </ul> 11</template> 12<script> 13import { mapState, mapActions } from 'vuex' 14export default{ 15 computed: 16 mapState(['products']), 17 methods: 18 mapActions(['addProductToCart']), 19 created(){ 20 this.$store.dispatch('getAllProducts') 21 } 22} 23</script>

ShoppingCart.vue

vue

1<template> 2 <div class="cart"> 3 <h2>あなたの買い物かご</h2> 4 <p v-show="cartProducts.length"><i>購入された商品が加算されていきます</i></p> 5 <ul> 6 <li 7 v-for="product in cartProducts" 8 :key="product.id"> 9 {{ product.title }} - {{ product.price }} x {{ product.quantity }} 10 </li> 11 </ul> 12 <p>合計: {{ cartTotalPrice }}円</p> 13 <p><button 14 :disabled="!cartProducts.length" 15 @click="avoidShopping(cartProducts)" 16 >キャンセル</button></p> 17 <p><button 18 :disabled="!cartProducts.length" 19 @click="checkout(cartProducts)" 20 >購入</button></p> 21 <p v-show="checkoutStatus">購入{{ checkoutStatus }}</p> 22 </div> 23</template> 24 25<script> 26import { mapGetters,mapState } from 'vuex' 27 28export default { 29 computed:{ 30 ...mapGetters(['cartProducts','cartTotalPrice']), 31 ...mapState(['checkoutStatus']), 32 }, 33 methods: { 34 //精算処理 35 checkout (products){ 36 this.$store.dispatch('checkout',products) 37 }, 38 //購入キャンセル(今回の質問部分に関与するメソッド) 39 avoidShopping(cartProducts){ 40 this.$store.dispatch('avoidShopping',cartProducts) 41 }, 42 }, 43} 44</script>

store.js

js

1import Vue from 'vue' 2import Vuex from 'vuex' 3 4Vue.use(Vuex) 5 6import shop from '@/api/shop.js' 7 8export default new Vuex.Store({ 9 state: { 10 products : [], //商品一覧 11 items: [], //買い物かごの中身 12 returns: [], //返却リスト 13 checkoutStatus: null, //購入処理の判定フラグ 14 }, 15 //データの更新 16 mutations: { 17 //商品の設定 18 setProducts(state, products){ 19 state.products = products; 20 }, 21 //カートへの投入 22 pushProductToCart(state, product){ 23 state.items.push({ 24 id: product.id, 25 quantity: 1, 26 }) 27 }, 28 //在庫への差し戻し 29 returnCartToProduct(state,cartItem){ 30 /*今回の質問部分(詳細は後述*/ 31 }, 32 //数量の加算 33 incrementItemQuantity(state,{ id}){ 34 const cartItem = state.items.find(item => item.id === id); 35 cartItem.quantity++; 36 }, 37 //在庫の減算 38 decrementProductInventory(state, { id }){ 39 const product = state.products.find( product => product.id === id) 40 product.inventory--; 41 }, 42 //買い物かごの設定 43 setCartItems(state,{items}){ 44 state.items = items 45 }, 46 //購入処理の設定 47 setCheckoutStatus(state,status){ 48 state.checkoutStatus = status 49 } 50 }, 51 //データの反映 52 actions: { 53 //商品の出力 54 getAllProducts(context){ 55 shop.getProducts(products => { 56 context.commit('setProducts', products); 57 }) 58 }, 59 //買い物かごへの追加と在庫の管理 60 addProductToCart({state,commit},product){ 61 const cartItem = state.items.find(item => item.id === product.id) //該当商品を制御 62 //console.log(cartItem) 63 if(!cartItem){ 64 commit('pushProductToCart',product) //カートに商品追加 65 }else{ 66 commit('incrementItemQuantity',cartItem) //カート内商品を加算 67 } 68 commit('decrementProductInventory',product) //在庫の減算 69 }, 70 //買い物完了後の処理 71 checkout({state,commit}, products){ 72 const savedCartItems = state.items 73 commit('setCheckoutStatus','購入前') 74 //買い物かごを空にする 75 commit('setCartItems',{items: []}) 76 77 shop.buyProducts( 78 products, 79 ()=> commit('setCheckoutStatus','完了'), 80 ()=>{ 81 commit('setCheckoutStatus','失敗') 82 commit('setCartItems',{items: savedCartItems}) 83 } 84 85 ) 86 }, 87 //購入のキャンセル(今回の質問に関与するaction) 88 avoidShopping({state,commit},products){ 89 commit('returnCartToProduct',{products}) //商品の在庫への返却 90 commit('setCartItems',{items: []}) //買い物かごを空にする 91 } 92 }, 93 getters:{ 94 //カートの反映 95 cartProducts: state =>{ 96 return state.items.map(item =>{ 97 const product = state.products.find(product => product.id === item.id) 98 return{ 99 title: product.title, 100 price: product.price, 101 quantity: item.quantity, 102 } 103 }) 104 }, 105 //金額の勘定 106 cartTotalPrice: (state,getters)=>{ 107 return getters.cartProducts.reduce((total,product)=>{ 108 return total + product.price * product.quantity //累計 + 単価*数量 109 },0) 110 } 111 } 112}) 113

前提・実現したいこと

購入キャンセル機能の実装。キャンセルボタンが押下されたタイミングで、買い物かごを空にし、在庫に対し、買い物かごに入った数量をそのまま差し戻す。ただし、購入処理が行われたものに対しては在庫として加算されない。

試したこと

色々試してみて実現させてみた(いちおう希望通りの動きは実現しています)のが以下のコードですが、引数も使用していないし、なにか方法が冗長にも感じます。もっとVuexに相応しい、適切な記述方法はないものでしょうか?

js

1mutations:{ 2 returnToProduct(state,cartItem){ 3 let returns = state.returns //キャンセル(在庫変更)リスト 4 let items = state.items //買い物かご変更用の在庫数量 5 returns = state.items.map(item =>{return item.id}) //在庫変更に対応したidの抽出 6 state.products.forEach((p,key)=>{ 7 if(returns.indexOf(p.id) !== -1){ 8 let idx = returns.indexOf(p.id) //在庫変更が必要な商品のid 9 p.inventory = p.inventory + items[idx].quantity //現在庫+買い物かごの数量 10 } 11 }) 12 } 13}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問