몽땅뚝딱 개발자

[Vue.js/에러일지] v-model cannot be used on v-for or v-slot scope variables because they are not writable. 본문

에러일지/Vue.js

[Vue.js/에러일지] v-model cannot be used on v-for or v-slot scope variables because they are not writable.

레오나르도 다빈츠 2022. 6. 21. 22:37

 

에러

v-model cannot be used on v-for or v-slot scope variables because they are not writable.

 

이 에러가 떠서 고군분투했다.

기존에는 값을 하나씩만 넘기다가 이번 케이스에선 오브젝트로 넘겨서 양방향 통신을 했어야했는데ㅠ 고것이 문제였다.

emit으로 update:value를 input, change 같은 온갖 이벤트로 다 넘겨보고 computed로도 감지해봤지만 몽땅 실패했다.

타입스크립트도 잘 모르고 Vue3도 잘 몰라서ㅠ 해결할 수 없을거라 생각했지만.... 해결은 됐다.

 

 


 

1. 인덱스를 명확히 지정해주자

이건 좀... 뭔가 말이 안되는 해결책이라고 생각이 들었지만.... 해보았고 역시나 안됐다..

잘 돌아가는 for문에 item[i]를 넣는건 좀 이상하게 느껴졌다.

 

[전]

<template v-for="(item, i) in list.length" :key="i">
  <div
    v-model="item"
  ></div>
</template>

 

[후]

<template v-for="(item, i) in list.length" :key="i">
  <div
    v-model="item[i]"
  ></div>
</template>

 

 

2. 그렇다면 props에 타입을 지정해줘야하는 것은 아닐까

정답을 찾았다고 생각했다...!! 하지만 아니었다.

하지만 미래의 내가 필요한 자료일 수도 있으므로... 남겨둔다.

const props = defineProps({
  modelValue: {
    type: Object as PropType<Range>,
    default: () => ({}),
  },
const props = defineProps({
  modelValue: {
    type: Object as PropType<Range>,
    default: () => {
      return {
        label: '',
        startVal: '',
        endVal: '',
      }
    },
  },

 

 

3. 그렇다면...!

인텔리제이에서는 아무런 문제가 없다고하는데 자꾸 브라우저에서는 니가 잘못했다며,, 둘 중 하나가 거짓말을 하고있었다.

결론은 바로 바로~~ emit을 사용하려고 했으면서 defineEmits를 import 하지 않은! 허무맹랑한 나의 실수였다 ^_^

 

비슷한 공통컴포넌트에서 코드를 가져오는 과정에서 그냥 붙여넣기만 하면서 import를 하지 않았다.

// import 부분에 defineEmits가 없다.
import { defineProps } from 'vue'
const emit = defineEmits(['delete', 'update:label'])

 


 

 

안되는 줄 알았지만~ 아주 간단히 오브젝트로 v-model로 연결하는게 가능하다.

이렇게!

<ChildComp
  v-model:label="item.label"
  v-model:end-val="item.endVal"
  v-model:start-val="item.startVal"
></ChildComp>

 

 

 

 


개인적으로 공부한 내용을 정리하는 블로그로
잘못된 개념을 게시하지않도록 주의하고 있으나 오류가 있을 수 있습니다.

 

 

Comments