TIL-Vue.js 시작하기

이고운·2023년 4월 17일
0

react와 비슷한 것 같기도 하고 배우기 조금 더 간단한 것 같아서 공부하기 시작했다.
공부하면서 보니 react랑 많이 비슷했다. 로직같은 건 동일하다고 보면 됨.
component만들고 prop 넘기는 것 같은 것들..
다만 차이가 있다면 그 넘기는 방식이 다르다는 것이다.
그 방법을 기록하고자 블로그에 작성 중!!!

0. Vue.js 사용하는 이유

  1. 쉬움 : 코드가 복잡할 수록 vue의 장점이 더 잘 보임
    html처럼 보여서 구조가 더 잘 보이는 장점이 있음.
  2. 답이 정해져있음 : react는 코드짜는 방법이 매우 다양함.
    예를 들어 반복문을 쓰더라도 map, forEach, for in, for of 등 다양함. 그러나 vue는 v-for한가지임.
  3. 빠름 : 렌더링 하는 시간이 빠름.
  4. 장기적인 지원 : 공식문서도 잘 되어있고, 버전도 업데이트 되고 있음.

1. Vue.js 시작하기

1) Vue.js 설치방법

  • npm install -g @vue/cli
  • 이후에 뜨는 버전 vue3으로 선택 후 설치
  • vue create 프로젝트명 입력
  • cd 프로젝트명
  • npm run serve로 서버 시작하기

** 특이한 방법이 서버 시작하는 방법 : react는 npm run start였는데
vue는 npm run serve이다!!

2. Vue.js 이용하기

1) 데이터

(1) 데이터 바인딩 방법

<template>

 <h4 :style="스타일">XX 원룸</h4>
    <p>{{price1}}</p>

</template>
<script>
export default {
  name : 'App',
  data(){
    return {
      price1 : 60,
      스타일 : 'color:red'
    }
  }
}

</script>

이런 식으로 data(){} 에 데이터 저장해주고 위에서 {{}}에서 사용해주면 됨. 참고로 class, id 등 HTML 속성도 데이터바인딩이 가능하다는 점이 신기함.

2) 반복문

(1) 반복문 사용하기 v-for

  1. 메뉴들안의 자료 갯수만큼 반복됨.
  2. 작명한 변수는 반복될 때마다 메뉴들 안에 있던 자료들이 됨.

v-for="작명 in 반복할횟수"

<a v-for="작명 in 메뉴들" :key="작명"> {{ 작명 }}</a>
>
//추가로 i 인덱스를 넣을 수도 있음.
<a v-for="(작명,i) in 메뉴들" :key="i"> {{ 작명 }}</a>

즉, array, object 데이터 안에 있던 자료들을 하나씩 HTML로 만들어서 보여주고 싶을 때도 v-for을 쓰면 유용함.

3) 이벤트 핸들러

(1) 이벤트 핸들러 사용하기

@click="자바스크립트함수"

** 이벤트 핸들러는 다양하게 있음.

(2) 상태값 저장 (react에서 state 상태 저장)

react에서는useState로 상태값을 저장해서 사용했다.
그러나 vue에서는 data(){}에서 현재 상태값을 저장해준 다음에 그값을 꽂아 넣으면 됨.
예를 들어 버튼을 클릭했을 때 숫자가 한개씩 증가하는 기능을 만들고 싶다고 하면 신고수를 기록할 수 있는 변수나 데이터를 하나 만들어 주고 그것에 대한 자바스크립트를 작성해 주면 되는 것.

<button @click="신고수++">허위매물신고</button>

data(){
  return {
    신고수 : 0,
  }
}

** 만약 @click함수가 너무 길다고 하면 아래에 함수를 만들어서 넣어주면 됨. 함수를 만드는 자리는 정해져 있음.
data(){} 아래에 methods : {} 항목을 신설해서 입력해주면 됨.

<button @click="increase()">허위매물신고</button>
data(){
  return {
    신고수 : 0,
  },
}

methods : { 
  increase(){ 
    this.신고수 += 1 
  } 
}

다만 여기서 주의해야할 점!!
여기서 데이터를 가져다쓰고 싶으면 꼭 this.데이터이름이라고 기재해야함.
this는 그냥 위에 있는 데이터와 함수를 담은 큰 object라고 생각하기.

4) component/props

(1) 조건문 v-if (모달창 만들기)

기존에 react로 모달창 만들 때는 state로 스위치를 만들어서 버튼 클릭시 true/false로 구분하여 모달창이 열리도록 구현함.
이번에도 원리는 비슷함. date()에 modalOpen:false로 현재값 저장하기
그리고 조건문을 달아서 modalOpen이 true일 때 모달 컴포넌트를 보여주면 됨.

<div class="black-bg" v-if="modalOpen == true">

<button @click="modalOpen = true"></button>

v-if="조건식"은 조건식이 참일 때만 html을 보여줌.
예를 들어 v-if="1 == 1"일 때 적용된다는 말 "1 == 2" 같이 거짓이면 적용 안됨.

** 상세페이지 만들기

모달창 안에 상세페이지를 만들 것임.
일단 긴배열로 만들어진 데이터를 js파일에 따로 만들어서 import해오는 방식은 똑같음.
가져온 데이터 중에서 하나의 카드를 누르면 그 카드에 해당되는 상세페이지가 모달창으로 뜨는 형식.

메인화면 //내가 클릭한 카드의 index번호를 state로 저장할 것임.
<div v-for="(a, i) in property" :key="i">
  <img :src="a.image" class="room-img">
  <h4 @click="modalOpen = true; clickNum = i">{{a.title}}</h4>
  <p>{{a.price}}</p>
</div>

data(){
  return {
    clickNum : 0
  }
}

모달창
<div class="black-bg" v-if="modalOpen == true">
  <div class="white-bg">
    <h4>{{ property[clickNum].title }}</h4>
    <p>상세페이지내용임</p>
  </div>
</div>

(2) component 만들기

component만들고 import해오는 것은 동일함.
다만 문법이 좀 다름.
component라는 항목에서 import해온 component를 기재해줘야함.

Discount.vue
블라블라블라

App.vue

<Discount/>
  
import Discount from './Discount.vue 경로'
export default {
  data() {

  },
  components : {
    Discount,
  }
}

(3) props 넘기는 방법

<Discount :데이터이름="오브젝트.name" :데이터이름="오브젝트.age"  />
//위 아래가 동일한 내용임  
<Discount v-bind="오브젝트명" />  

(4) 부모에 있는 props수정 = custom event

원래 자식은 부모에 있는 props 수정 못함.
부모에게 메세지는 보내는 것.
$emit('작명', 데이터)

그 다음 부모 컴포넌트에서 이렇게 받아야함.
@작명=""

Card.vue

<h4 @click="$emit('openModal')">


App.vue

<Card @openModal="modalOpen = true"/>

그런데 여기까지하면 어떤 번호의 카드를 눌렀는지 모름.
그래서 몇번째 눌렀는지 알아야함. 여기서는 id임. 그래서 아래와 같이 보내고 받음.
(여기서 한번 에러가 생겼는데 작명 넣을 때 꼭 ""가 아닌 ''이어야 한다!!
별생각없었는데 꼭 구분하기)

Card.vue

 <h4 @click="$emit('openModal', property.id)">


App.vue

<Card @openModal="modalOpen = true; clickNum = $event"/>

자식이 보낸 데이터는 $event에 담겨있음.
(사실 여기선 그냥 App.vue clickNum=i로 해도 먹힘)

👉 추가)
$emit()methods{}안에서 사용하고 싶을 때

<h4 @click="함수명">
methods{
   함수명(){
   this.$emit('openModal', this.property.id)}
   }

이렇게 해도 됨. 주의할 것은 this 붙이기 (함수 안에서 참조할 때 this)

(5) input 값 받아오기 v-model

(1)
<input @input="month = $event.target.value" />

(2)
<input v-model="month" />

data() {
    return {
      month: 1,
    };
  },

위 아래가 똑같은 의미임. react에서 input값 받아올 때 e.target.value를 사용하는데 vue에서도 맥락은 비슷함.
다만, 앞에 $기호를 넣음. $event는 event object라는 것을 뜻함.
@input 유사품 @change도 있음.
참고로 v-model은 입력값을 데이터로 바꿔서 저장하라 라는 문법

++ input,textarea,select 적용 가능
혹은 input type="checkbox" 등으로 변경해도 가능.

+++ 여기서 input에 적은 값은 문자임.
그래서 확실하게 숫자로 변환할 때는
<input v-model.number="month" /> 이런 식으로 directive을 사용하면 숫자로 반환해줌.

👉 추가)

input에 제한 두는 법 - watcher

예를 들어 input에 문자두면 경고문주기

watcher = 데이터를 감시하는 함수
watch(){감시할데이터(){}}
해당 데이터가 변경될 때마다 watcher도 실행됨.
** 유의할 점은 꼭 함수명을 특이하게도 내가 감시하고 싶은 데이터명으로 작명

<input v-model.number="month" />
   
data() {
    return {
      month: 1,
    };
  },
  watch: {
    month(num) {
      if (isNaN(num) == true) {
        alert("문자입력하지마");
        this.month = 1;
      }
    },
  },

이런 식으로 month의 데이터가 숫자가 아니면 경고문구를 나오게 하고 싶다고 한다면 watch항목 안에 month()이름으로 함수를 만들고 그곳에 조건식을 달면 됨.
참고로 watch()안에 파라미터가 두개까지 들어갈 수 있는데, 첫째는 변경될 값, 둘째는 변경전 값을 의미

5) transition

vue에서 에니메이션을 줄 때 css로 하면 된다는 점이 react같지만
class에 속성을 주는 법이 독특했다. 그리고 태그를 이용하는 방법도 새로웠다.

(1) class 속성

class에 데이터를 줄 수 있었는데 그 데이터가 true일 때 해당 클래스명을 부착하게 된다.

<div :class="{ 클래스명 : true }"> </div>

예를 들어, 모달창이 열릴 때 에니메이션을 주고 싶다고 하면
기본적으로 class에 (시작하는 클래스명) css로 opacity랑 transition을 준 다음에, 끝날 때 적용할 클래스 명을 적되, 여기서는 모달창이 오픈될 때 이다. 즉, modalOpen state가 true일때 css가 적용되길 원하므로
:class="{끝날때 적용할 클래스명 : modalOpen}"이 되는 것이다.

<div class="start" :class="{ end: modalOpen }">

(2)transition tag

애니메이션 주고 싶은 UI를 태그로 감싼다.
<transition name="작명"></transition>
그리고 아래와 같이 css를 주면됨 약간 공식 같은 것.

.class명-enter-from { 애니메이션 동작 전 상태 }
.class명-enter-active { 애니메이션 동작 중 상태, 대부분 transition 이런거 }
.class명-enter-to { 애니메이션 동작 후 상태 }

위의 코드는 에니메이션 등장 시에 적용할 css라 start인 것이고
만약 에니메이션 퇴장 시에 적용할 것이라면 중간을 leave로 변경하면 된다.

6) 데이터 정렬

가격 순으로 카드를 정렬할 예정임.

(1) sort 메소드

let array = [3, 5, 4]
array.sort(function(a,b){
  return a - b
  })

그런데 이렇게 sort메소드를 사용하게 되면 sort메소드는 원본을 변경하는 메소드이기 때문에 정렬을 원래대로 바꿀 때 작업이 필요함.
(즉 sort로 변경한 property 배열이 아예 변경되었다는 뜻임.)
spread operator문법을 사용했다. 사본을 만들어서 저장해주기

  • 먼저 내가 가진 카드들의 배열을 스프레드 오퍼레이터로 사본 저장해준다.
  • 그리고 property배열에 만들어둔 원본을 넣어준다.
 <button @click="priceSort">가격순 정렬</button>
 <button @click="sortBack">원래대로</button>
 
 data() {
  propertyOrigin: [...property], //사본을 하나 저장
  property: property,
  }
 
 
 methods: {
    priceSort() {
      this.property.sort(function (a, b) {
        return a.price - b.price;
      });
    },
    sortBack() {
      this.property = [...this.propertyOrigin];//사본을 다시 원배열에 넣어줌.
    },
  }

7) Lifeycle hook

라이프사이클 중간 중간에 훅을 걸 수 있음.
react에서 했던 것과 마찬가지로 useEffect를 이용해서 렌더링될 때 실행하게 하다던가 하는 것과 비슷함.
vue에는 아래와 같은 함수가 있음.

beforeCreate()
created() //데이터 생성
beforeMount()
mounted() //index.html 파일에 장착
beforeUpdate()
updated() //재렌더링
beforeUnmount()
unmounted() //다른페이지로 이동하거나 그럴 때 컴포넌트가 삭제

공식문서 다이어그램

❗️에러

.vue파일에서 <scirpt>안에 name 속성이 들어가는데, 이 때 이름에 multi-word가 들어가지 않으면 에러가 뜬다.
검색해보니 다른 요소와의 충돌을 피하기 위해 이렇게 에러가 뜨는 것이라고 함.
물론 다중글자로 넣으면 좋겠지만 이를 무시하는 방법도 있긴 하다.

{
  "vue/multi-word-component-names": ["error", {
    "ignores": []
  }]
}

"ignores( string[]) ... 무시할 구성 요소 이름입니다. 허용할 구성 요소 이름을 설정합니다."라고 공식 문서에 적혀있음. 즉 여기에 무시할 이름을 적으면 됨.

또 한가지 방법은 vue.config.js파일에서 lintOnSave:false로 한줄 기재해주면 된다.

module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
});

esLint는 자바스크립트 파일의 오류를 잡기 위해 오류 나는 사항을 알려주는 것인데, 그 기능을 끄는 것임.
하지만, 이 것은 기능을 끄는 것이니까 별로 맘에 들지 않는다...
package.json
rules에 "vue/multi-word-component-names": "off" 추가하면된다는데 난 왜 안되는지 모르겠다.. 원칙상 다중글자로 넣는게 맞으니까 그렇게 넣어야지...

⭐️ 완성본

profile
자 이제 시작이야~ 내 꿈을~ 내 꿈을 위한 여행~~🌈

0개의 댓글