채용공고를 찾아보며 힘들게 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>
- Vue만의 데이터 보관함을 만듭니다.
- 데이터를 "{{ }}" 안에 넣어주어 연결합니다.
- 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>
- 데이터 보관함에 배열을 만듭니다.
- 다음과 같이 반복문을 만들어 여러 개의 태그를 만들 수 있습니다. 문법만 익히면 기존 개념과 비슷하며 다음과 같이 화면에 보입니다.
이벤트 핸들러
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>
- Vue만의 함수 보관함 methods를 만들어 안에 넣습니다.
- onClick이 아닌 @click 속성이고 함수를 연결해 주면 됩니다.
- 간단한 함수는 태그 안에서 구현해도 괜찮습니다.
모달 만들기
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>
- 모달의 상태를 데이터로 설정해 줍니다.
- v-if 속성을 이용하여 모달의 상태를 연결해 줍니다. v-if 속성은 조건이 참일 때만 태그가 활성화됩니다.
- 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>
- 데이터를 보내고 받아옵니다. default로 보냈기에 유동적으로 이름을 정할 수 있습니다.
- 이미지 역시 데이터에서 속성을 연결하기에 ":"를 앞에 넣어줍니다.
- 새 변수를 만들어 누르는 항목과 내용이 연결되게 합니다.
- 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>
- 간단한 컴포넌트 파일을 만듭니다.
- 그 파일을 데려옵니다.
- 컴포넌트 보관함에 넣어주고 별칭도 넣을 수 있습니다.
- 그 파일을 태그와 똑같이 사용하면 됩니다.
프롭스와 커스텀 이벤트
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>
- 프롭스로 데이터를 전해주는 방법은 컴포넌트 태그에 ":별칭 = 데이터" 이렇게 속성을 넣어주면 됩니다.
- 그리고 이 데이터들은 하위 컴포넌트에서 props 보관함을 만들어 데이터들의 자료형을 정의해줘야 합니다.
- 프롭스로 내려받은 데이터는 변경 불가, 즉 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 |