Vue3

sooni·2023년 4월 27일
0

vue3-vite-ts project

목록 보기
3/3

Vue2에서 이미 Composition API를 사용하고 있어 큰 차이점은 느끼지 못했지만 간단히 Vue2와 Vue3의 차이점을 정리해본다.

주목할만한 새로운 기능

많은 변경들 중 Vue3에서 주목해야할 새로운 기능은 아래와 같다.

  • Composition API
  • <script setup>
  • Fragments
  • Emits Component Option
  • 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 에서도 사용가능하다.

Composition API

Vue2에서는 data, computed, methods, created, watch를 모두 하나씩 생성해야 했지만 Vue3에서는 Composition API를 통해 setup 함수 안에서 모두 생성할 수 있다. 이 때, setup 함수 안에서 생성한 data는 this로 접근하지 않는다.

Composition API를 사용하는 가장 큰 장점은 목적에 맞는 코드를 모듈화해 유연하고 확장이 가능하다.

자세한 내용은 링크 에서 확인 가능하다.

<script setup>

Composition API를 사용하게되면서 SFC(Single-File Components) 내에서 사용가능하며 다음과 같은 이점이 있다.

  • 더 적은 상용구로 간결한 코드 작성
  • typescript 사용 시 props와 emit 선언
  • 런타임 성능 향상 (템플릿이 <script setup>과 같은 scope에 있는 render 함수로 컴파일 되어 proxy가 불필요)
  • IDE 타입 추론 성능 향상

Top-level bindings are exposed to template

기존 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>

Using Components

component를 바로 사용할 수 있다.

<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

defineProps() & defineEmits()

propsemits를 defineProps()와 defineEmits()로 선언 가능하다.

<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>

Usage alongside normal <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>

더 많은 설정은 공식 문서에서 확인 가능하다.

Fragments

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>

Emits Component Option

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 in <style>

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>

key usage on v-for, v-if

Vue3에서는 key를 자동으로 생성해주고 있으므로 직접 key 설정하는것을 권장하지 않는다.

v-if

// 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>

0개의 댓글