defineModel을 파헤치다.

찬찬잉·2023년 8월 25일
1

defineModel 은 vue 3.3에서 새롭게 추가 된 기능 중 한 가지이다.

이젠 vueuse에서 사용되던 useModel과 유사한 기능을 제공하고있는데...

이번에 추가 된 내용을 자세하게 보고 싶다면 에반유의 블로그 & 깃헙을 통해 확인할 수 있다.

나는 2023년 8월 23일 회사 내에서 리뷰를 진행하고 부족한 부분이 있어 다시금 정리를 해보려고 한다.

내용에 앞서 나는 아무것도 모르는 주니어 개발자기에... 꼭 블로그와 깃헙을 다시금 확인해보시길...


defineModel을 사용하기 앞서 제일 먼저 vue-loader@^17.1.1 업그레이드와 vite.config에 추가 설정을 해줬어야했다.

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue({
    script: {
      defineModel: true,
      propsDestructure: true
    }
  })],
})

vue.config.js

module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => {
        return {
          ...options,
          defineModel: true
        }
      })
  }
}

위와 같이 코드를 설정해준 후에 사용이 가능하다는 점은 깃헙에도 표기되어있으니 꼭 설정하시길 바란다.

블로그에서 처음으로 나온 내용은 defineModel이 없을 때 사용하는 방법이었다.

<!-- BEFORE -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
console.log(props.modelValue)

function onInput(e) {
  emit('update:modelValue', e.target.value)
}
</script>

<template>
  <input :value="modelValue" @input="onInput" />
</template>

우리가 예전에 사용하던 방식은 이렇다는 내용
v-model에 modelValue를 선언하고 emit을 통해 업데이트 해야하는 update:propName을 전달해야한다. 이렇게 해야 양방향을 지원하게 되는데 이번 vue 3.3에서 변경 된 defineModel을 사용하면

<!-- AFTER -->
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>

<template>
  <input v-model="modelValue" />
</template>

v-model에 선언한 modelValue를 바로 defineModel()로 연결하여 자동으로 props하고 emit까지 처리할 수 있는 ref를 반환하게 된다.

위에서 살펴 본 내용 외 깃헙에 있는 내용을 살펴 보면
첫 번째 인수가 문자열이면 prop 이름으로 사용됩니다. 그렇지 않으면 prop 이름은 기본적으로 "modelValue"로 설정됩니다. 두 경우 모두 prop의 옵션으로 사용할 추가 개체를 전달할 수도 있습니다. 에 따라 기본 이름은 modelValue인 것을 확인할 수 있다.

자식 컴포넌트

<template>
  <input v-model="modelValue">
</template>

<script setup>
const modelValue = defineModel()
</script>

부모 컴포넌트

<template>
  <Comp v-model="msg">
</template>

<script setup>
import { ref } from 'vue'
import Comp from './Comp.vue'

const msg = ref('')
</script>

또한 필수로 지정하도록할 수 있는데 그것은 옵션을 지정하면 된다.

const modelValue = defineModel<string>({ required: true })

위 코드에서 {내부} reuired와 같이 필수 값으로 지정해서 사용이 가능하다.

const count = defineModel<number>('count')

물론 첫번째 인자에 이름을 지정해서 보낼 수 있다. '이름', {옵션}
순으로 지정해서 보낼 수 있다.

const count = defineModel<number>('count', { default: 0 })

위 코드는 이름과 기본값을 포함해서 보낸 예시이다.

또한 props는 하더라도 emit은 안하도록할 수 있는데 그것은

const count = defineModel<number>('count', { local: true, default: 0 })

위 코드에서 local 을 사용하면 된다.

defineModel을 살펴보았다.
사용하면서 진짜 편하긴했다... 근데 난 제대로 이해하고 쓰진 못했던 것 같다... defineModel을 emit과 props로 다시 쪼개는 작업을 못하는 상황이었기에... 그래서 더욱 이해해보고자 작성 중 이다..

모두들 화이팅...

profile
디자이너, 기획자 출신의 개발자

0개의 댓글