react와 비슷한 것 같기도 하고 배우기 조금 더 간단한 것 같아서 공부하기 시작했다.
공부하면서 보니 react랑 많이 비슷했다. 로직같은 건 동일하다고 보면 됨.
component만들고 prop 넘기는 것 같은 것들..
다만 차이가 있다면 그 넘기는 방식이 다르다는 것이다.
그 방법을 기록하고자 블로그에 작성 중!!!
- 쉬움 : 코드가 복잡할 수록 vue의 장점이 더 잘 보임
html처럼 보여서 구조가 더 잘 보이는 장점이 있음.- 답이 정해져있음 : react는 코드짜는 방법이 매우 다양함.
예를 들어 반복문을 쓰더라도 map, forEach, for in, for of 등 다양함. 그러나 vue는 v-for한가지임.- 빠름 : 렌더링 하는 시간이 빠름.
- 장기적인 지원 : 공식문서도 잘 되어있고, 버전도 업데이트 되고 있음.
** 특이한 방법이 서버 시작하는 방법 : react는 npm run start였는데
vue는 npm run serve이다!!
<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 속성
도 데이터바인딩이 가능하다는 점이 신기함.
v-for="작명 in 반복할횟수"
<a v-for="작명 in 메뉴들" :key="작명"> {{ 작명 }}</a>
>
//추가로 i 인덱스를 넣을 수도 있음.
<a v-for="(작명,i) in 메뉴들" :key="i"> {{ 작명 }}</a>
즉, array, object 데이터 안에 있던 자료들을 하나씩 HTML로 만들어서 보여주고 싶을 때도 v-for을 쓰면 유용함.
@click="자바스크립트함수"
** 이벤트 핸들러는 다양하게 있음.
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라고 생각하기.
기존에 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>
component만들고 import해오는 것은 동일함.
다만 문법이 좀 다름.
component라는 항목에서 import해온 component를 기재해줘야함.
Discount.vue
블라블라블라
App.vue
<Discount/>
import Discount from './Discount.vue 경로'
export default {
data() {
},
components : {
Discount,
}
}
<Discount :데이터이름="오브젝트.name" :데이터이름="오브젝트.age" />
//위 아래가 동일한 내용임
<Discount v-bind="오브젝트명" />
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
)
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 = 데이터를 감시하는 함수
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()안에 파라미터가 두개까지 들어갈 수 있는데, 첫째는 변경될 값, 둘째는 변경전 값을 의미
vue에서 에니메이션을 줄 때 css로 하면 된다는 점이 react같지만
class에 속성을 주는 법이 독특했다. 그리고 태그를 이용하는 방법도 새로웠다.
class에 데이터를 줄 수 있었는데 그 데이터가 true일 때 해당 클래스명을 부착하게 된다.
<div :class="{ 클래스명 : true }"> </div>
예를 들어, 모달창이 열릴 때 에니메이션을 주고 싶다고 하면
기본적으로 class에 (시작하는 클래스명) css로 opacity랑 transition을 준 다음에, 끝날 때 적용할 클래스 명을 적되, 여기서는 모달창이 오픈될 때 이다. 즉, modalOpen state가 true일때 css가 적용되길 원하므로
:class="{끝날때 적용할 클래스명 : modalOpen}"
이 되는 것이다.
<div class="start" :class="{ end: modalOpen }">
애니메이션 주고 싶은 UI를 태그로 감싼다.
<transition name="작명"></transition>
그리고 아래와 같이 css를 주면됨 약간 공식 같은 것.
.class명-enter-from { 애니메이션 동작 전 상태 }
.class명-enter-active { 애니메이션 동작 중 상태, 대부분 transition 이런거 }
.class명-enter-to { 애니메이션 동작 후 상태 }
위의 코드는 에니메이션 등장 시에 적용할 css라 start
인 것이고
만약 에니메이션 퇴장 시에 적용할 것이라면 중간을 leave
로 변경하면 된다.
가격 순으로 카드를 정렬할 예정임.
let array = [3, 5, 4]
array.sort(function(a,b){
return a - b
})
그런데 이렇게 sort메소드를 사용하게 되면 sort메소드는 원본을 변경하는 메소드이기 때문에 정렬을 원래대로 바꿀 때 작업이 필요함.
(즉 sort로 변경한 property 배열이 아예 변경되었다는 뜻임.)
spread operator
문법을 사용했다. 사본을 만들어서 저장해주기
<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];//사본을 다시 원배열에 넣어줌.
},
}
라이프사이클 중간 중간에 훅을 걸 수 있음.
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"
추가하면된다는데 난 왜 안되는지 모르겠다.. 원칙상 다중글자로 넣는게 맞으니까 그렇게 넣어야지...