+ 00 00 0000

Have any Questions?

07_Simple Coding – Vue Cart – 기본 요약

07_Simple Coding – Vue Cart – 기본 요약

📃 요약

Html 1 페이지로 웹 사이트를 개발하는 라이브러리임, SPA(Single Page Application)이라고 함, html첫페이지에서 변경되는 부분만 .js 소스(컴포넌트)로 불여서 개발하는 방식이 흡사 레고블럭을 연결해서 하나의 완성본을 만드는 것과 같다고 해서 컴포넌트 개발이라고도 함, 과거 코딩방식보다 일부 변경된 부분만 바꾸어 끼우는 방식이라서 성능이 비약적으로 증가함, 현대 프론트 코딩방식은 SPA 개발로 바뀌고 있으며 비슷한 계열로 React / Angular 가 있음

요소 기술 :

– Basic : Vue

📃 기술 구현

스펙 :

- vscode
- js (es6)
- vue

📃 Vue

- 컴포넌트 프로그래밍 : 페이지를 컴포넌트로 분리해서 레고 블럭처럼 조립해서 코딩하는 방식을 채택함, Vue, React 등이 적용하고 있음
- Vue 프레임워크라고 하고, 필수 라이브러리들이 대체로 설치되어 있고 제어문/반복문이 쉬워 초보자가 접근하기 쉬움
- 리액트는 라이브러리라고 하며 필수 라이브러리들을 추가적으로 설치해야 하고 제어문/반복문이 모던js 를 기반으로 다양하게 사용되기때문에
배워야 하는 기술이 많아 초보자가 접근하기에는 어려운 측면이 있음

Vue 디렉토리 구조 : 역할별로 파일을 나누어 폴더별로 관리됨

1) public        : html 1개가 있는 위치, 주로 외부 라이브러리 cdn 들이 위치됨
2) src           : Vue 소스 파일들 위치, 다양한 하위폴더로 구성
    - assets     : 이미지, css, 외부 js 등이 위치함
    - components : 페이지에서 공통으로 사용할 자식 컴포넌트 위치
    - router : url 과 컴포넌트(페이지) 규칙 정의 js
    - store      : 전역(공유) 변수/함수 정의하는 js
    - views      : 페이지 컴포넌트가 있는 위치
 3) App.vue      : 최초 실행되는 뷰 파일 
    - 여기서 모든 컴포넌트가 조립됨
 4) main.js      : 최초로 실행되는 js 파일
    - 모든 자식 컴포던트에서 사용될 js, css import 시 여기서 import 되어 사용됨 

📃 Vue 사용법 : vue-cli 를 이용한 사용법

– vue-cli :

주로 개발은  vue-cli 를 이용해 개발이 이루어짐 아래 예제들은 vue-cli 기반으로 설명함

  • vue-cli 설치 : 컴퓨터에 1번만 설치하면 됨


    사용법 : npm install -g @vue/cli


  • 프로젝트 만들기


    사용법 : vue create 프로젝트명


  • 프로젝트 실행



    사용법 : npm run serve

- 프로젝트 종료
```bash
사용법 : ctrl + c (키보드 타이핑 2번)
  • node_modules : 뷰 설치파일이 있는곳 , 사이즈가 큼
    1) 사이즈가 큼
    2) 주로 다른 팀원에게 뷰 소스를 줄때 삭제후 전달하고, 팀원이 인터넷에서 다사 설치파일을 내려받아 재생성함
    3) 재생성 명령어 : npm install
    사용법 : npm install

📃 Vue Cart 예제 : 뷰 공식사이트 예제를 vue-cli 기반 코딩으로 수정해서 소개

1 환경 설정

1) 부트스트랩 추가 
2) 디자인 파일 import 

1) 부트스트랩 추가

- 위치 : index.html
- cdn : 부트스트랩 5.2.x css cdn & js cdn 추가

– public/index.html

<!DOCTYPE html>
<html lang="">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title>
    <%= htmlWebpackPlugin.options.title %>
  </title>
  <!-- 부트스트랩 link -->
  <!-- Latest compiled and minified CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
        Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
  <!-- bootstrap js link -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
    crossorigin="anonymous"></script>
</body>

</html>

2) styles.css : cart 디자인 파일 import

- 위치 : App.vue
- 추가 : @import 예약어로 css 파일 import
  1) @import "경로/styles.css";

– App.vue

<template>
  <div id="app">
    <HeaderCom />

    <router-view/>
  </div>
</template>
<script>
import HeaderCom from "@/components/HeaderCom.vue";

export default {
    components : {
        HeaderCom
    }
}
</script>
<style lang="scss">
@import "@/assets/css/styles.css";
</style>

3) HeaderCom.vue : 부트스트랩 메뉴가 있는 위치

- 머리말(메뉴) 컴포넌트
- components 폴더에 위치함
- App.vue 에서 자식컴포넌트를 조립해서 사용함

– HeaderCom.vue

- 사용법 :
<template>
  <nav class="navbar navbar-expand-lg bg-light">
    <div class="container-fluid">
      <a class="navbar-brand" href="#">Navbar</a>
      <button
        class="navbar-toggler"
        type="button"
        data-bs-toggle="collapse"
        data-bs-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent"
        aria-expanded="false"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="/">Home</a>
          </li>
          <li class="nav-item dropdown">
            <a
              class="nav-link dropdown-toggle"
              href="#"
              role="button"
              data-bs-toggle="dropdown"
              aria-expanded="false"
            >
              Basic 메뉴
            </a>
            <ul class="dropdown-menu">
              <li>
                <router-link to="/binding" class="dropdown-item"
                  >Binding</router-link
                >
              </li>
              <li>
                <router-link to="/binding-exam" class="dropdown-item"
                  >Binding-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/condition" class="dropdown-item"
                  >Condition</router-link
                >
              </li>
              <li>
                <router-link to="/condition-exam" class="dropdown-item"
                  >Condition-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/list" class="dropdown-item">List</router-link>
              </li>
              <li>
                <router-link to="/list-exam" class="dropdown-item"
                  >List-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/event" class="dropdown-item"
                  >Event</router-link
                >
              </li>
              <li>
                <router-link to="/event-exam" class="dropdown-item"
                  >Event-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/class" class="dropdown-item"
                  >Class</router-link
                >
              </li>
              <li>
                <router-link to="/class-exam" class="dropdown-item"
                  >Class-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/computed" class="dropdown-item"
                  >Computed</router-link
                >
              </li>
              <li>
                <router-link to="/computed-exam" class="dropdown-item"
                  >Computed-Exam</router-link
                >
              </li>
              <li>
                <router-link to="/form" class="dropdown-item">Form</router-link>
              </li>
            </ul>
          </li>
        </ul>
      </div>
    </div>
  </nav>
</template>
<script>
export default {};
</script>
<style lang=""></style>

– App.vue

<template>
  <div id="app">
    <HeaderCom />

    <router-view/>
  </div>
</template>
<script>
import HeaderCom from "@/components/HeaderCom.vue";

export default {
    components : {
        HeaderCom
    }
}
</script>
<style lang="scss">
@import "@/assets/css/styles.css";
</style>

2 예제 순서 :

1) BindingView.vue     : 바인딩 변수 예제
2) ConditionView.vue   : if/else if/else 문 예제
3) ListView.vue        : for 문 예제
4) EventView.vue       : 이벤트 함수 예제
5) ClassView.vue       : class / style 사용법 예제
6) ComputedView.vue    : computed 함수 예제
7) FormView.vue        : form 양식 예제

1) BindingView.vue : 바인딩 변수 예제

- 위치 : views/exam01

– BindingView.vue

<template>
  <div class="home">
    <!-- TODO: -->
    <h1>{{ product }}</h1>
    <p>I love {{ product }}</p>
  </div>
</template>

<script>
// @ is an alias to /src
export default {
  data() {
    return {
      product: "Lamp",
    };
  },
};
</script>

2) ConditionView.vue : if/else if/else 문 예제

- 위치 : views/exam02

– ConditionView.vue

<template lang="">
  <div id="app">
    <div class="nav-bar"></div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <h1>{{ product }}</h1>

          <!-- TODO:  -->
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>
          <!--  visibility 속성 -->
          <!-- <p v-show="inStock">In Stock</p> -->
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      product: "Socks",
      image: require("@/assets/images/socks_green.jpg"),
      inStock: true,
    };
  },
};
</script>
<style lang=""></style>

3) ListView.vue : for 문 예제

- 위치 : views/exam03

– ListView.vue

<template lang="">
  <div id="app">
    <div class="nav-bar"></div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <h1>{{ product }}</h1>
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>

          <!-- TODO: -->
          <ul>
            <li v-for="(detail, index) in details" :key="index">
              {{ detail }}
            </li>
          </ul>

          <!-- TODO: key 값에 따라 Collection객체 출력 -->
          <ul>
            <li v-for="variant in variants" :key="variant.id">
              {{ variant.color }}
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      product: "Socks",
      image: require("@/assets/images/socks_green.jpg"),
      inStock: true,
      details: ["50% cotton", "30% wool", "20% polyester"],
      variants: [
        { id: 2234, color: "green" },
        { id: 2235, color: "blue" },
      ],
    };
  },
};
</script>
<style lang=""></style>

4) EventView.vue : 이벤트 함수 예제

- 위치 : views/exam04

– EventView.vue

<template>
  <div id="app">
    <div class="nav-bar"></div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <h1>{{ product }}</h1>
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>
          <ul>
            <li v-for="(detail, index) in details" :key="index">
              {{ detail }}
            </li>
          </ul>

          <!-- key 값에 따라 Collection객체 출력 -->
          <ul>
            <li v-for="variant in variants" :key="variant.id">
              {{ variant.color }}
            </li>
          </ul>

          <!-- TODO: key 값에 따라 Collection객체 출력 -->
          <div
            v-for="variant in variants"
            :key="variant.id"
            @mouseover="updateImage(variant.image)"
          >
            {{ variant.color }}
          </div>
          <button class="button" v-on:click="addToCart">Add to Cart</button>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      product: "Socks",
      image: require("@/assets/images/socks_green.jpg"),
      inStock: true,
      details: ["50% cotton", "30% wool", "20% polyester"],
      variants: [
        { id: 2234, color: "green" },
        { id: 2235, color: "blue" },
      ],
    };
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateImage(variantImage) {
      this.image = variantImage;
    },
  },
};
</script>
<style lang=""></style>

5) ClassView.vue : class / style 사용법 예제

- 위치 : views/exam05

– ClassView.vue

<template>
  <div id="app">
    <div class="nav-bar"></div>

    <!-- TODO:  -->
    <div class="cart">Cart({{ cart }})</div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <h1>{{ product }}</h1>
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>
          <ul>
            <li v-for="(detail, index) in details" :key="index">
              {{ detail }}
            </li>
          </ul>

          <!-- TODO: class, style 추가 -->
          <div
            v-for="variant in variants"
            :key="variant.id"
            @mouseover="updateImage(variant.image)"
            class="color-circle"
            :style="{ 'background-color': variant.color }"
          >
            {{ variant.color }}
          </div>
          <button
            class="button"
            v-on:click="addToCart"
            :class="{ disabledButton: !inStock }"
            :disabled="!inStock"
          >
            Add to Cart
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      cart: 0,
      product: "Socks",
      image: require("@/assets/images/socks_green.jpg"),
      inStock: true,
      details: ["50% cotton", "30% wool", "20% polyester"],
      variants: [
        { id: 2234, color: "green", image: require("@/assets/images/socks_green.jpg") },
        { id: 2235, color: "blue", image: require("@/assets/images/socks_blue.jpg") },
      ],
    };
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateImage(variantImage) {
      this.image = variantImage;
    },
  },
};
</script>
<style lang=""></style>

6) ComputedView.vue : computed 함수 예제

- 위치 : views/exam06

– ComputedView.vue

<template>
  <div id="app">
    <div class="nav-bar"></div>

    <div class="cart">Cart({{ cart }})</div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <!-- computed 이용해서 title = brand + 공백 + product -->
          <h1>{{ title }}</h1>
          <!-- 연습문제 inStock > 0 보일수 있게 -->
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>
          <ul>
            <li v-for="(detail,index) in details" :key="index">{{ detail }}</li>
          </ul>

          <!-- key 값에 따라 Collection객체 출력 -->
          <div
            v-for="(variant, index) in variants"
            :key="variant.id"
            @mouseover="updateVariant(index)"
            class="color-circle"
            :style="{ 'background-color': variant.color }"
          ></div>
          <button
            class="button"
            :class="{ disabledButton: !inStock }"
            :disabled="!inStock"
            @click="addToCart"
          >
            Add to Cart
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      cart: 0,
      product: "Socks",
      brand: "Vue Mastery",
      selectedVariant: 0,
      details: ["50% cotton", "30% wool", "20% polyester"],
      variants: [
        {
          id: 2234,
          color: "green",
          image: require("@/assets/images/socks_green.jpg"),
          quantity: 50,
        }, // index 0
        {
          id: 2235,
          color: "blue",
          image: require("@/assets/images/socks_blue.jpg"),
          quantity: 0,
        }, // index 1
      ],
    };
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateVariant(index) {
      this.selectedVariant = index;
    },
  },
  computed: {
    title() {
      return this.brand + " " + this.product;
    },
    image() {
      return this.variants[this.selectedVariant].image;
    },
    // 연습문제
    inStock() {
      return this.variants[this.selectedVariant].quantity;
    },
  },
};
</script>
<style lang=""></style>

7) FormView.vue : form 양식 예제

- 위치 : views/exam07

– FormView.vue

<template>
  <div id="app">
    <div class="nav-bar"></div>

    <div class="cart">Cart({{ cart }})</div>

    <div class="product-display">
      <div class="product-container">
        <div class="product-image">
          <!-- image goes here  -->
          <img :src="image" />
        </div>

        <div class="product-info">
          <!-- <h1>{{ product }}</h1> -->
          <!-- TODO: computed 이용해서 title = brand + 공백 + product -->
          <h1>{{ title }}</h1>
          <p v-if="inStock">In Stock</p>
          <p v-else>Out of Stock</p>
          <ul>
            <li v-for="(detail, index) in details" :key="index">
              {{ detail }}
            </li>
          </ul>

          <!-- key 값에 따라 Collection객체 출력 -->
          <div
            v-for="variant in variants"
            :key="variant.id"
            @mouseover="updateImage(variant.image)"
            class="color-circle"
            :style="{ 'background-color': variant.color }"
          ></div>
          <button
            class="button"
            :class="{ disabledButton: !inStock }"
            :disabled="!inStock"
            @click="addToCart"
          >
            Add to Cart
          </button>
        </div>
      </div>
    </div>

    <!-- TODO: form 추가 -->
    <form class="review-form" @submit.prevent="onSubmit">
      <h3>Leave a review</h3>
      <label for="name">Name:</label>
      <input id="name" v-model="name" />

      <label for="review">Review:</label>
      <textarea id="review" v-model="review"></textarea>

      <label for="rating">Rating:</label>
      <select id="rating" v-model="rating">
        <option>5</option>
        <option>4</option>
        <option>3</option>
        <option>2</option>
        <option>1</option>
      </select>
      <input class="button" type="submit" value="Submit" />
    </form>
    <!-- TODO: 결과 출력 -->
    <div class="review-container">
      <h3>Reviews:</h3>
      <ul>
        {{
          name
        }}
        gave this
        {{
          rating
        }}
        stars
        <br />
        "{{
          review
        }}"
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      cart: 0,
      product: "Socks",
      brand: "Vue Mastery",
      selectedVariant: 0,
      details: ["50% cotton", "30% wool", "20% polyester"],
      variants: [
        {
          id: 2234,
          color: "green",
          image: require("@/assets/images/socks_green.jpg"),
          quantity: 50,
        }, // index 0
        {
          id: 2235,
          color: "blue",
          image: require("@/assets/images/socks_blue.jpg"),
          quantity: 0,
        }, // index 1
      ],
      name: "",
      review: "",
      rating: null,
    };
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateVariant(index) {
      this.selectedVariant = index;
    },
    onSubmit() {
        alert("제출되었습니다.");
    }
  },
  computed: {
    title() {
      return this.brand + " " + this.product;
    },
    image() {
      return this.variants[this.selectedVariant].image;
    },
    // 연습문제
    inStock() {
      return this.variants[this.selectedVariant].quantity;
    },
  },
};
</script>
<style lang=""></style>

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다