ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 15일차
    정보교육/프런트엔드 2024. 7. 4. 20:11

    9장 Pinia로 상태 관리하기
    9.4 실습: Pinia를 사용해 장바구니 앱 만들기

    1. 뷰 애플리케이션 초기화

    //vue.js.frontend/ch09_cart/src/router/index.js
    import { createRouter, createWebHistory } from 'vue-router'
    import HomeView from '../views/HomeView.vue'
    
    const router = createRouter({
      history: createWebHistory(import.meta.env.BASE_URL),
      routes: [
        {
          path: '/',
          name: 'home',
          component: HomeView
        },
        {
          path: '/cart',
          name: 'cart',
          // route level code-splitting
          // this generates a separate chunk (About.[hash].js) for this route
          // which is lazy-loaded when the route is visited.
          component: () => import('../views/CartView.vue')
        }
      ]
    })
    
    export default router
    // vue.js.frontend/ch09_cart/src/stores/cart.js
    import { reactive } from 'vue'
    import { defineStore } from 'pinia'
    
    export const useCartStore = defineStore('cart', () => {
      const item = reactive([
        {
          id: 1,
          name: 'banana',
          price: 1000,
        },
        {
          id: 2,
          name: 'orange',
          price: 3000,
        },
        {
          id: 3,
          name: 'mango',
          price: 5000,
        },
        {
          id: 4,
          name: 'apple',
          price: 4000,
        },
      ]);
      const cartItem = reactive([]);  // 장바구니 아이템
      
      return { item, cartItem }
    })
    // vue.js.frontend/ch09_cart/src/views/CartView.vue
    <script setup>
    
    </script>>
    
    <template>
      <h1>장바구니 목록</h1>
    </template>
    // vue.js.frontend/ch09_cart/src/views/HomeView.vue
    <script setup>
    
    </script>>
    
    <template>
      <h1>상품 목록</h1>
    </template>
    // vue.js.frontend/ch09_cart/src/App.vue
    <script setup>
    import { RouterLink, RouterView } from 'vue-router'
    </script>
    
    <template>
      <RouterView />
    </template>
    // vue.js.frontend/ch09_cart/src/main.js
    // import './assets/main.css'
    
    import { createApp } from 'vue'
    import { createPinia } from 'pinia'
    
    import App from './App.vue'
    import router from './router'
    
    const app = createApp(App)
    
    app.use(createPinia())
    app.use(router)
    
    app.mount('#app')

    2. 상품 목록 구현하기

    // vue.js.frontend/ch09_cart/src/views/HomeView.vue
    <script setup>
    import { useCartStore } from '@/stores/cart';
    import { storeToRefs } from 'pinia';
    const cartStore = useCartStore();
    // item 비구조화 할당
    const { item } = storeToRefs(cartStore);
    // 장바구니에 상품 추가 기능, cartItem에 id 추가
    const inCart = (id) => {
      cartStore.cartItem.push(id);
    };
    // 장바구니에 상품 삭제 기능, cartItem에 id 삭제
    const outCart = (id) => {
      cartStore.cartItem = cartStore.cartItem.filter((v) => v !== id);
    };
    </script>>
    
    <template>
      <h1>상품 목록</h1>
      <RouterLink to="/cart">장바구니</RouterLink>
      <ul>
        <li
          v-for="it in item"
          :key="it.id"
          :class="{ in: cartStore.cartItem.includes(it.id)}">
          <span>{{ it.name }}</span>
          <span>{{ it.price }}</span>
          <button
            v-if="!cartStore.cartItem.includes(it.id)"
            @click="inCart(it.id)">담기</button>
          <button v-else @click="outCart(it.id)">삭제</button>
        </li>
      </ul>
    </template>
    
    <style scoped>
    .in {
      text-decoration: line-through;
    }
    </style>

    3. 장바구니 구현하기

    // vue.js.frontend/ch09_cart/src/views/CartView.vue
    <script setup>
    import { useCartStore } from '@/stores/cart';
    import { computed } from 'vue';
    const cartStore = useCartStore();
    // cartItem에 포함되어 있지 않은 item 값만 필터링
    const cartItem = computed(() => {
      return cartStore.item.filter((v) => cartStore.cartItem.includes(v.id));
    });
    // cartItem 스테이트 값 비우기
    const allClear = () => {
      cartStore.cartItem = [];
    };
    // 장바구니에 담긴 전체 금액을 합산해 alert()으로 보여주기
    const payCart = () => {
      const price = cartItem.value.reduce((prev, cur) => {
        return prev + cur.price;
      }, 0);
      alert('총 ${price.toLocaleString()}원을 결제하시겟습니까?');
    };
    // 장바구니에서 상품 삭제 기능
    const outCart = (id) => {
      // cartStore.cartItem = cartStore.cartItem.filter((v) => v !== id); 이 코드는 HomeView와 중복되어 스토어에 보냄.
      cartStore.outCart(id);
    };
    </script>
    
    <template>
      <h1>장바구니 목록</h1>
      <RouterLink to="/">Home</RouterLink>
      <ul v-if="cartItem.length > 0">
        <li v-for="item in cartItem">
          <span>{{ item.name }}</span>
          <span>{{ item.price }}</span>
          <button @click="outCart(item.id)">삭제</button>
        </li>
      </ul>
      <p v-else>장바구니가 비어 있습니다</p>
      <button @click="payCart">결제</button>
      <button @click="allClear">전체 비우기</button>
    </template>
Designed by Tistory.