본문 바로가기
VUE

Vue 기초 2

by 일태찡 2023. 4. 14.

 

input 데이터 받기

 

ProductModal.vue

<template>
  <div class="black-bg" v-if="onModal">
    <div class="white-bg">
      <input @input="month = $event.target.value" /> <!--1-->
      <input v-model.number="month"> <!--2-->
      <p>{{ productLists[productIndex].price * month }}</p>
    </div>
  </div>
</template>

<script>
export default {
  name: "ProductModal",
  data() {
    return {
      month: 1,
    };
  },
  props: {
    productLists: Array,
    productIndex: Number,
  },
};
</script>

 

  1. 인풋 태그를 만들고 다음과 같이 사용자의 입력을 month 데이터에 넣어줄 수 있습니다. "@input" 속성은 입력이 변할 때마다 적용되고 "@change"속성은 입력하고 사용자가 인풋 창을 벗어날 때 적용됩니다.
  2. 이렇게 "v-model" 속성으로 위와 똑같은 기능을 수행하는 코드를 작성할 수 있습니다. 이 속성은 정보를 받는 모든 태그에 적용이 가능합니다. 또 받아오는 데이터는 모두 문자열이기 때문에 속성 뒤에 타입을 지정해서 받을 수 있습니다.

 

watcher로 데이터 감시

 

ProductModal.vue

<template>
  <div class="black-bg" v-if="onModal">
    <div class="white-bg">
      <img :src="productLists[productIndex].image" style="width: 100%" />
      <h4>{{ productLists[productIndex].title }}</h4>
      <p>{{ productLists[productIndex].content }}</p>
      <input v-model.number="month">
      <p>{{ productLists[productIndex].price * month }}</p>
      <button @click="$emit('closeModal')">close</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "ProductModal",
  data() {
    return {
      month: 1,
    };
  },
  // 여기
  watch : {
    month(data, prevData) {
      if(isNaN(data)) {
        alert("숫자를 입력하세요!");
        this.month = 1;
      }
      console.log(prevData);
    }
  },
  props: {
    productLists: Array,
    productIndex: Number,
    onModal: Boolean,
  },
};
</script>

 

다음과 같이 데이터 이름과 같은 함수를 watch 보관함에 만들 수 있습니다. 이는 데이터가 변할 때마다 실행하는 함수를 의미하며 지금은 숫자 말고 다른 것을 입력했을 때 경고를 보내고 값을 1로 바꿉니다. 게다가 이 함수는 두 번째 인자로 데이터의 변하기 전 가장 최근 값을 불러올 수 있습니다.

 

 

모달 스타일 작업

 

App.vue

<template>
  <!--2-->
  <div class="start" :class="{ end: onModal }">
    <ProductModal
      :productLists="productLists"
      :productIndex="productIndex"
      :onModal="onModal"
      @closeModal="onModal = false"
    />
  </div>
</template>

<style>
body {
  margin: 0;
}
div {
  box-sizing: border-box;
}
#app {
// 1
.start {
  opacity: 0;
  transition: all 1s;
}
.end {
  opacity: 1;
}
</style>

 

  1. 다음과 같이 클래스를 두 개 정의합니다.
  2. 동적으로 모달이 활성화되면 클래스에 "end"가 추가되게 합니다. "end" 속성은 옆 조건이 참일 경우에만 켜지게 됩니다.

 

App.vue

<template>
  <transition name="fade">
    <ProductModal
      :productLists="productLists"
      :productIndex="productIndex"
      :onModal="onModal"
      @closeModal="onModal = false"
    />
  </transition>
</template>

<style>
.fade-enter-from {
  opacity: 0;
}
.fade-enter-active {
  transition: all 1s;
}
.fade-enter-to {
  opacity: 1;
}

.fade-leave-from {
  opacity: 1;
}
.fade-leave-active {
  transition: all 1s;
}
.fade-leave-to {
  opacity: 0;
}
</style>

 

Vue는 transition 태그를 이용하여 위와 똑같이 구현할 수 있습니다. 그리고 style에 name과 상황을 단계별로 나눠 그에 맞게 스타일을 부여할 수 있습니다.

 

 

상품 정렬

 

App.vue

<template>
  <!--1-->
  <button @click="priceUp">Price↑</button>
  <button @click="priceDown">Price↓</button>
  <button @click="sortBack">Reset</button>
  
  <ProductCard
    v-for="item in productLists"
    :key="item.id"
    :product="item"
    :productIndex="productIndex"
    @openModal="
      onModal = true;
      productIndex = $event;
    "
  />
</template>

<script>
import data from "./assets/dummyData";

import ProductCard from "./components/ProductCard.vue";

export default {
  name: "App",
  data() {
    return {
      productListsCopy: [...data], // 2
      productLists: data,
      productIndex: 0,
      onModal: false,
    };
  },
  methods: {
    // 1
    priceUp() {
      this.productLists.sort((a, b) => a.price - b.price);
    },
    priceDown() {
      this.productLists.sort((a, b) => b.price - a.price);
    },
    // 2
    sortBack() {
      this.productLists = [...this.productListsCopy];
    }
  },
  components: {
    Discount: DiscountBanner,
    ProductModal: ProductModal,
    ProductCard: ProductCard,
  },
};
</script>

 

  1. 버튼을 만들고 상품의 가격에 따라 정렬하는 함수를 만들어 연결해 줍니다.
  2. sort는 기존 배열을 바꿔버리기에 사본을 따로 만들어 저장하고 정렬을 해제할 때 그 사본을 넣어줍니다. 배열은 등호로 넣게 되면 값의 대입이 아닌 공유이기에 사본의 사본을 전달해 줍니다.

 

Vue의 라이프 사이클

 

Vue의 lifecycle

 

  1. create 단계 - 데이터만 존재
  2. mount  단계 - template 태그 사이에 있던 HTML을 렌더링
  3. component 생성 단계
  4. update 단계- HTML의 실시간 리렌더링
  5. unmount 단계 - component 삭제

 

이렇게 간단하게 단계를 나눌 수 있지만 중요한 점은 위 사이클에서 빨간 점 선으로 표시된 훅들입니다. 이는 단계 사이사이마다 훅을 걸어 코드를 집어넣고 생성할 수 있게 됩니다.

 

App.vue

<template>
  <Discount v-if="showDiscount" />
</template>

<script>
import data from "./assets/dummyData";

import DiscountBanner from "./components/DiscountBanner.vue";

export default {
  name: "App",
  data() {
    return {
      showDiscount: true,
    };
  },
  methods: {},
  created() {
    // AJAX 요청
  },
  mounted() {
    setTimeout(() => {
      this.showDiscount = false;
    }, 2000);
  },
  components: {
    Discount: DiscountBanner,
  },
};
</script>

 

Discount 컴포넌트가 마운트 되고 2초 후 사라지게 하는 코드입니다. script 태그 안에 훅을 설정해 주고 안에 실행할 코드를 넣어주면 됩니다. 보통 통신으로 데이터를 받을 때 created 훅이나 mounted 훅을 사용합니다. 또 그 외의 모든 단계 사이에 훅을 걸 수 있습니다.

'VUE' 카테고리의 다른 글

Vuex  (6) 2023.04.21
slot 과 mitt  (7) 2023.04.20
Vue를 이용한 여러 기능 구현  (7) 2023.04.19
Vue 라우팅  (7) 2023.04.17
Vue 기초 1  (6) 2023.04.13