Vue2에서 이미 Composition API를 사용하고 있어 큰 차이점은 느끼지 못했지만 간단히 Vue2와 Vue3의 차이점을 정리해본다.
많은 변경들 중 Vue3에서 주목해야할 새로운 기능은 아래와 같다.
<script setup>
v-bind
in <style>
key
usage on v-for
, v-if
Composition API, <script setup>
, Emits Component Option, v-bind
in <style>
은 Vue 2.7 에서도 사용가능하다.
Vue2에서는 data, computed, methods, created, watch
를 모두 하나씩 생성해야 했지만 Vue3에서는 Composition API를 통해 setup 함수 안에서 모두 생성할 수 있다. 이 때, setup 함수 안에서 생성한 data는 this
로 접근하지 않는다.
Composition API를 사용하는 가장 큰 장점은 목적에 맞는 코드를 모듈화해 유연하고 확장이 가능하다.
자세한 내용은 링크 에서 확인 가능하다.
Composition API를 사용하게되면서 SFC(Single-File Components) 내에서 사용가능하며 다음과 같은 이점이 있다.
<script setup>
과 같은 scope에 있는 render 함수로 컴파일 되어 proxy가 불필요)기존 setup() 함수 내에서 return해서 사용했던 것과 다르게 <script setup>
사용 시 return 없이 사용 가능하다.
<script setup>
import { ref } from 'vue'
// variable
const count = ref(0)
const msg = 'Hello!'
// functions
function log() {
console.log(msg)
}
</script>
<template>
<button @click="log">{{ msg }}</button>
<button @click="count++">{{ count }}</button>
</template>
import 사용도 마찬가지이다.
<script setup>
import { capitalize } from './helpers'
</script>
<template>
<div>{{ capitalize('hello') }}</div>
</template>
component를 바로 사용할 수 있다.
<script setup>
import MyComponent from './MyComponent.vue'
</script>
<template>
<MyComponent />
</template>
props
와 emits
를 defineProps()와 defineEmits()로 선언 가능하다.
<script setup>
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
// setup code
</script>
일반 <setup>
과 함께 사용 가능하다.
<script>
// normal <script>, executed in module scope (only once)
runSideEffectOnce()
// declare additional options
export default {
inheritAttrs: false,
customOptions: {}
}
</script>
<script setup>
// executed in setup() scope (for each instance)
</script>
더 많은 설정은 공식 문서에서 확인 가능하다.
Vue2에서는 단일 루트 노드만을 지원했지만 Vue3는 다중 루트 컴포넌트를 지원한다. 그러나 공식적으로는 단일 루트를 지향하는것이 좋다 한다.
// vue 2
<template>
<!-- OK -->
<div></div>
</template>
<template>
<!-- ERROR -->
<div></div>
<div></div>
</template>
// vue 3
<template>
<!-- OK -->
<div></div>
<div></div>
</template>
Vue2에서는 별도로 emit을 지정하는 부분이 없었지만 Vue3 에서는 props와 마찬가지로 emit을 정의할 수 있다. array 형식으로 정의하거나 object 형식으로 선언할 수 있다.
// vue 3
// array 형식
<script>
export default {
emits: ['check', 'submit'],
methods: {
submitMethod() {
this.$emit('submit', { email, password });
}
}
}
</script>
// object 형식
<script>
export default {
emits: {
click: null, // validation이 필요 없는 경우
submit: (payload) => { // validation이 필요한 경우
if (payload.email && payload.password) {
return true;
} else {
console.warn(`Invalid submit event payload!`);
return false;
}
}
},
methods: {
submitMethod() {
this.$emit('submit', { email, password });
}
}
}
</script>
v-bind로 template에서 정의한 변수를 style에서 사용 가능하다.
// vue 3
<script setup>
const theme = {
color: 'red'
}
</script>
<template>
<p>hello</p>
</template>
<style scoped>
p {
color: v-bind('theme.color');
}
</style>
Vue3에서는 key를 자동으로 생성해주고 있으므로 직접 key 설정하는것을 권장하지 않는다.
// vue 2
<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>
// vue 3
<div v-if="condition">Yes</div>
<div v-else>No</div>
Vue2에서 <template>
태그에는 key
를 사용할 수 없어 child component에 설정해야 했지만 Vue3에서는 <template>
태그에도 key
를 설정할 수 있다.
// vue 2
<template v-for="item in list">
<div :key="'heading-' + item.id">...</div>
<span :key="'content-' + item.id">...</span>
</template>
// vue 3
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>