v-model throws ReferenceError only in Production

Issue

I have the following View in Vue:

<script setup>
import Overwrite from "../components/Overwrite.vue";
</script>
<template>
  <div>

      ...

      <textarea v-model="text" cols="99" rows="20"></textarea>

      ... 

  </div>
</template>

<script>
export default {
  data() {
    return {
      text: ""
    };
  },
  components: { Overwrite: Overwrite },
};
</script>

Everything works perfectly fine when I start the application with npm run dev.

However, when I build the app for production and run it, I get the following error as soon as I type anything into the textarea:

index.57b77955.js:3 Uncaught ReferenceError: text is not defined
    at HTMLTextAreaElement.t.onUpdate:modelValue.s.<computed>.s.<computed> [as _assign] (index.57b77955.js:3:1772)
    at HTMLTextAreaElement.<anonymous> (vendor.31761432.js:1:53163)

I also have other form elements that show the exact same behaviour.

Solution

You can use a maximum of 1 × <script> tag and a maximum of 1 × <script setup> per vue component.

Their outputs will be merged and the object resulting from merging their implicit or explicit exports is available in <template>.

But they are not connected. Which means: do not expect any of the two script tags to have visibility over the other one’s imports.

The worst part is that, although the first <script setup> does declare Ovewrite when you import it (so it should become usable in <template>), the second one overwrites it when you use components: { Overwrite: Overwrite }, because Overwrite is not defined in the second script. So your components declaration is equivalent to:

components: { Overwrite: undefined }

, which overwrites the value already declared by <script setup>.


This gives you two possible solutions:

Solution A:

<script>
import Overwrite from "../components/Overwrite.vue";
export default {
  components: {
    Overwrite
  },
  // you don't need `data` (which is Options API). use `setup` instead
  setup: () => ({
    text: ref('')
  })
}
</script>

Solution B:

<script setup>
import Overwrite from "../components/Overwrite.vue";
const text = ref('')
</script>

Or even:

<script setup>
import Overwrite from "../components/Overwrite.vue";
</script>
<script>
export default {
  data: () => ({ text: "" })
};
</script>

Answered By – tao

Answer Checked By – Pedro (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.