본문 바로가기
VUE

Vue 기초 1

by 일태찡 2023. 4. 13.

 

채용공고를 찾아보며 힘들게 Vue 안 쓰는 곳만 고르고 고르다 지쳐서 그냥 배워보기로 했습니다...

 

 

Vue의 장점

 

  • 일단 SPA 웹 앱 개발 툴 React, Angular, Vue 3대장 중 가장 쉽습니다.
  • 다른 코드와 다르게 개발하는 방식이 다양하지 않아 스타일 통일이 쉽습니다.
  • HTML 렌더링이 빨라 실시간으로 반영하기 좋습니다.
  • 꾸준히 업데이트되기에 장기적으로 지원이 좋습니다.

 


 

개발환경 설정

 

npm install -g @vue/cli
vue create first-practice
npm run serve

 

  • Vue 개발을 위한 라이브러리를 설치합니다.
  • Vue 프로젝트를 생성합니다.
  • 프로젝트 실행하여 화면에 출력합니다.

 

기본 구조

 

<template>
  
</template>

<script>
export default {

}
</script>

<style>

</style>

 

이렇게 파일 하나에 화면을 렌더링 하는 template 부분과 데이터, 함수 등을 저장하는 script, css를 설정하는 style 세 구역으로 나눠져 있습니다.

 

 

데이터바인딩

 

App.vue

<template>
  <div>
    <h4 :style="sold">행복 원룸</h4> <!--3-->
    <p>월세: {{ price1 }}만원</p> <!--2-->
  </div>
  <div>
    <h4>평화 원룸</h4>
    <p>월세: {{ price2 }}만원</p> <!--2-->
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      price1: 50, // 1
      price2: 70,
      sold: "color: red",
    };
  },
  components: {},
};
</script>

 

  1. Vue만의 데이터 보관함을 만듭니다.
  2. 데이터를 "{{ }}" 안에 넣어주어 연결합니다.
  3. HTML 속성에도 바인딩 가능하며 속성 앞에 ":"를 추가하면 됩니다.

 

 

반복문

 

App.vue

<template>
  <div class="menu">
    <a v-for="(item, index) in menuLists" :key="index">{{ item }}</a> <!--2-->
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      menuLists: ['Home', 'Products', 'About'], // 1
    };
  },
  components: {},
};
</script>

 

  1.  데이터 보관함에 배열을 만듭니다.
  2. 다음과 같이 반복문을 만들어 여러 개의 태그를 만들 수 있습니다. 문법만 익히면 기존 개념과 비슷하며 다음과 같이 화면에 보입니다.

 

 

이벤트 핸들러

 

App.vue

<template>
  <div>
    <h4>{{ products[0] }}</h4>
    <p>월세: 50만원</p>
    <button @click="reportCount += 1">허위매물신고</button> <!--3-->
    <button @click="increase">허위매물신고</button> <!--2-->
    <span>신고: {{ reportCount }}</span>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      products: ["율전동 원룸", "연수동 원룸", "역삼동 원룸"],
      reportCount: 0,
    };
  },
  // 1
  methods: {
    increase(){
      this.reportCount += 1;
    }
  },
  components: {},
};
</script>

 

  1. Vue만의 함수 보관함 methods를 만들어 안에 넣습니다.
  2. onClick이 아닌 @click 속성이고 함수를 연결해 주면 됩니다.
  3. 간단한 함수는 태그 안에서 구현해도 괜찮습니다.

 

 

모달 만들기

 

App.vue

<template>
  <div class="black-bg" v-if="onModal" @click="onModal = false"> <!--2-->
    <div class="white-bg">
      <h4>상세페이지</h4>
      <p>내용</p>
    </div>
  </div>

  <div>
    <img src="./assets/room0.jpg" class="room-img" />
    <h4 @click="onModal = true">{{ products[0] }}</h4> <!--3-->
    <p>월세: 50만원</p>
    <button @click="increase(0)">허위매물신고</button>
    <span>신고: {{ reportCount[0] }}</span>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      menuLists: ["Home", "Products", "About"],
      products: ["율전동 원룸", "연수동 원룸", "역삼동 원룸"],
      reportCount: [0, 0, 0],
      onModal: false, // 1
    };
  },
  methods: {
    increase(index) {
      this.reportCount[index] += 1;
    },
  },
  components: {},
};
</script>

 

  1. 모달의 상태를 데이터로 설정해 줍니다.
  2. v-if 속성을 이용하여 모달의 상태를 연결해 줍니다. v-if 속성은 조건이 참일 때만 태그가 활성화됩니다.
  3. h4 태그를 누를 시 모달이 활성화됩니다.

 

 

더미데이터로 리팩토링

 

dummyData.js

더보기
// 1
export default [
  {
    id: 0,
    title: "Sinrim station 30 meters away",
    image: "https://codingapple1.github.io/vue/room0.jpg",
    content: "18년 신축공사한 남향 원룸 ☀️, 공기청정기 제공",
    price: 340000,
  },
  {
    id: 1,
    title: "Changdong Aurora Bedroom(Queen-size)",
    image: "https://codingapple1.github.io/vue/room1.jpg",
    content: "침실만 따로 있는 공용 셰어하우스입니다. 최대 2인 가능",
    price: 450000,
  },
  {
    id: 2,
    title: "Geumsan Apartment Flat",
    image: "https://codingapple1.github.io/vue/room2.jpg",
    content: "금산오거리 역세권 아파트입니다. 애완동물 불가능 ?",
    price: 780000,
  },
  {
    id: 3,
    title: "Double styled beds Studio Apt",
    image: "https://codingapple1.github.io/vue/room3.jpg",
    content: "무암동인근 2인용 원룸입니다. 전세 전환가능",
    price: 550000,
  },
  {
    id: 4,
    title: "MyeongIl Apartment flat",
    image: "https://codingapple1.github.io/vue/room4.jpg",
    content: "탄천동 아파트 월세, 남향, 역 5분거리, 허위매물아님",
    price: 680000,
  },
  {
    id: 5,
    title: "Banziha One Room",
    image: "https://codingapple1.github.io/vue/room5.jpg",
    content: "반지하 원룸입니다. 비올 때 물가끔 새는거 빼면 좋아요",
    price: 370000,
  },
];

 

 

App.vue

<template>
  <!--Navigation-->
  <div class="menu">
    <div v-if="isLogin == false">Login</div> <!--4-->
    <div v-else>Logout</div> <!--4-->
    <a v-for="(item, index) in menuLists" :key="index">{{ item }}</a>
  </div>

  <!--Modal-->
  <div class="black-bg" v-if="onModal">
    <div class="white-bg">
      <h4>{{ productLists[productIndex].title }}</h4> <!--3-->
      <p>{{ productLists[productIndex].content }}</p> <!--3-->
      <button @click="onModal = false">닫기</button>
    </div>
  </div>

  <!--Product-->
  <div v-for="item in productLists" :key="item.id">
    <img :src="item.image" class="room-img" /> <!--2-->
    <!--3-->
    <h4
      @click="
        onModal = true;
        productIndex = item.id;
      "
    >
      {{ item.title }}
    </h4>
    <p>{{ item.price }}</p>
  </div>
</template>

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

export default {
  name: "App",
  data() {
    return {
      productLists: data,
      menuLists: ["Home", "Products", "About"],
      onModal: false,
      productIndex: 0,
      isLogin: false,
    };
  },
  methods: {},
  components: {},
};
</script>

 

  1. 데이터를 보내고 받아옵니다. default로 보냈기에 유동적으로 이름을 정할 수 있습니다.
  2. 이미지 역시 데이터에서 속성을 연결하기에 ":"를 앞에 넣어줍니다.
  3. 새 변수를 만들어 누르는 항목과 내용이 연결되게 합니다.
  4. v-else 속성을 이용하여 위 조건이 참이 아닐 경우 아래 태그가 활성화됩니다. 또 v-else-if를 이용하여 추가적으로 구현이 가능합니다.

 

 

컴포넌트 나누기

 

DIscountBanner.vue

<template>
    <!--1-->
    <div class="discount">
    <h4>지금 결제하면 20% 할인</h4>
  </div>
</template>

<script>
export default {
    name: "DiscountBanner",
}
</script>

 

App.vue

<template>
  <!--4-->
  <Discount />
</template>

<script>
import DiscountBanner from "./components/DiscountBanner.vue"; // 2

export default {
  name: "App",
  data() {
    return {
    };
  },
  methods: {
  },
  // 3
  components: {
    Discount: DiscountBanner,
  },
};
</script>

 

  1. 간단한 컴포넌트 파일을 만듭니다.
  2. 그 파일을 데려옵니다.
  3. 컴포넌트 보관함에 넣어주고 별칭도 넣을 수 있습니다.
  4. 그 파일을 태그와 똑같이 사용하면 됩니다.

 

 

프롭스와 커스텀 이벤트

 

 

App.vue

<template>
  <ProductCard
    v-for="item in productLists"
    :key="item.id"
    :product="item" // 1
    :productIndex="productIndex"
    :onModal="onModal"
    @openModal=" // 3
      onModal = true;
      productIndex = $event;
    "
  />
</template>

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

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

export default {
  name: "App",
  data() {
    return {
      productLists: data,
      productIndex: 0,
      onModal: false,
    };
  },
  methods: {},
  components: {
    ProductCard: ProductCard,
  },
};
</script>

 

ProductCard.vue

<template>
  <div>
    <img :src="product.image" class="room-img" />
    <h4 @click="$emit('openModal', product.id)"> // 3
      {{ product.title }}
    </h4>
    <p>{{ product.price }}</p>
  </div>
</template>

<script>
export default {
  name: "ProductCard",
  // 2
  props: {
    product: Object,
    productIndex: Number,
    onModal: Boolean,
  },
};
</script>

 

  1. 프롭스로 데이터를 전해주는 방법은 컴포넌트 태그에 ":별칭 = 데이터" 이렇게 속성을 넣어주면 됩니다.
  2. 그리고 이 데이터들은 하위 컴포넌트에서 props 보관함을 만들어 데이터들의 자료형을 정의해줘야 합니다.
  3. 프롭스로 내려받은 데이터는 변경 불가, 즉 Read-Only이기 때문에 커스텀 이벤트 형식으로 부모 컴포넌트에게 알려줘야 합니다. 이는 하위 컴포넌트에서 변경을 수행하지 말고 "$emit"을 통해 메시지만 담아 전달하고 부모 컴포넌트에서 그 메시지에 함수를 달아줍니다. 또 데이터도 담아 보낼 수 있으며 "$event"를 통해 받을 수 있습니다.

 


 

처음엔 또 배워야 하나 걱정이 많았는데 생각보다 코드도 심플하고 일단 세 구역으로 명확히 나눠서 정리할 수 있는 부분이 너무 마음에 들었다! 걱정은 이 편안함에 길들여지면... 다른 툴이 쓰고 싶을지 걱정이긴 하다...

'VUE' 카테고리의 다른 글

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