Vue3 사용을 위해 공식문서를 다시한번 읽어보면서 놓쳤던 부분에 대해 정리한다.
this.$data.newProp = 1
로 새로운 data를 추가할 수 있지만, Reactivity system으로 감싸지지않았기때문에 변경시 추적은 불가능하다.
화살표함수를 사용해선 안된다.
화살표함수는 this가 없기때문에, 렉시컬컨텍스트를 따라 상위스코프의 this에 접근하게된다.
실행시점에 Vue내부에서 this가 vm을 가르키게 되므로 반드시 함수리터럴을 이용해서 정의하도록 한다.
템플릿 내부에서 사용될 경우, 순수함수로 작성하자.
API를 처리하는 비동기함수의 호출이 필요할 경우 라이프사이클훅에서 사용하도록 하자.
템플릿 내부에서 사용되면 리렌더링의 기준이된다.
method가 템플릿 내부에서 사용되면, method가 사용하고있는 data 가 변경되면 렌더링도 다시 이루어진다.
둘은 기능상으로 완전히 동일하다.
그러나 Computed는 캐싱이된다.
즉 computed에 정의된 값들은 의존성이 있는 반응형 데이터가 변했을때만 다시 계산한다.
그렇다고 값을 return하는 함수에대해서 매번 Computed를 사용하는게 좋은 것 만은 아니다.
반응형 데이터가 변했을때만 값을 재계산 하기 때문에, 다음 computed는 매번 같은값을 return한다.
computed: {
now() {
return Date.now()
}
}
computed는 따로 정의를 하지만 기본적으로 getter만 정의되지만, setter도 정의가 가능하다.
// ...
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
watch
가 아닌 computed
를 사용하자. 가독성도 올라가고 cache효과도 누릴 수 있다.watch
는 특정데이터가 변했을때, 메소드가 호출되거나 하는 경우에만 사용하자. (비동기, API 호출등의 메소드)template에서 바인딩될 수 있는 모든 property 들은 vm의 최상단으로 노출된다.
v-if
vs v-show
v-if
는 조건에 부합할대만 rendering을 한다.
v-show
는 조건에 상관없이 일단 rendering을 하고, 조건에 따라 display 속성을 통해 노출/비노출 처리를 한다.
둘은 같이 사용하는것을 권하지 않는다.
만약 같이 선언이 되었다면 v-if
가 먼저 계산되기떄문에 원치않는 동작이 발생할 수 있다.
v-for
의 우선순위를 높이고싶다면, template
감싸 v-for
를 먹인 후 내부 자식컴포넌트에서 v-if
를 적용한다.
<template v-for="todo in todos" :key="todo.name">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
v-for의 대상은 반드시 Array일 필요는 없다.
Object의 경우 property를 순회한다.
<li v-for="(value, name) in myObject">
{{ name }}: {{ value }}
</li>
,
를 이용해서 여러개의 콜백을 등록할 수 있다.
<button @click="one($event), two($event)">
Submit
</button>
event.preventDefault
, event.stopPropogation
과 같은 처리를 하기위해 $event
를 굳이 받아서 methods
내부에서 처리되는 것 보다, methods
내부에는 비지니스 로직만 처리하고, $event
와 관련된 작업은 modifer를 이용하여 콜백등록시점에 처리하는게 깔끔하다.
AS-IS
<template>
<form @submit="onSubmit($event)"></form>
</template>
// in component
methods: {
onSubmit (event) {
event.preventDefault();
event.stopPropagation();
if (event.currentTarget === event.target) {
// ...do something
}
}
}
TO-BE
<template>
<form @submit.prevent.stop.self="onSubmit"></form>
</template>
// in component
methods: {
onSubmit () {
// ...do something
}
}
keyup
과 같은 이벤트에서 특정키 입력에 대한 체크를 템플릿의 선언부에서 할 수 있다.
<template>
<!-- only call `vm.submit()` when the `key` is `Enter` -->
<input @keyup.enter="submit" />
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
</template>
입력받은 데이터에 대한 trim
, parseInt
와 같은 처리를 쉽게 할 수 있다.
<input v-model.number="age" type="text" />
<input v-model.trim="msg" />
사용자정의 컴포넌트에도 v-model을 사용할 수 있다.
사용자정의 컴포넌트에서는 modelValue
로 v-model 값에 접근하고, update:modelValue
로 v-model의 값을 바꿀 수 있다.
<custom-input v-model="searchText"></custom-input>
<!-- is same as -->
<custom-input
:model-value="searchText"
@update:model-value="searchText = $event"
></custom-input>
app.component('custom-input', {
props: ['modelValue'],
emits: ['update:modelValue'],
template: `
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
`
})
// or
app.component('custom-input', {
props: ['modelValue'],
emits: ['update:modelValue'],
template: `
<input v-model="value">
`,
computed: {
value: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
}
}
}
})