menu

Questions & Answers

Vue.js 3 typescript script setup vs not using setup

Can someone explain why this does not work with script setup, but without it works.
In the template I use v-for to iterate through the string[]:

<div v-for="lang in data.translatedLanguages" class="translationTableBodyRow">
      <div class="translationTableBodyCell">xx</div>
      <div class="translationTableBodyCell">{{ lang }}</div>
      <div class="translationTableBodyCell">10 %</div>
      <div class="translationTableBodyCell">Edit</div>
</div>

Code with <script lang="ts">:
Working, the v-for finds elements and I see the rows.

<script  lang="ts">
import axios, {isCancel, AxiosError} from 'axios';
import { defineComponent } from 'vue'

export default defineComponent({
    data() {
        return {
            data: { translatedLanguages: [] }
        }
    },
    mounted() {
        axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => {
            console.log(response.request.response);
            this.data = JSON.parse(response.request.response)
            this.data.translatedLanguages
            console.log(this.data.translatedLanguages);
        });
    }
});
</script>

Script with <script setup lang="ts">:
Not working, I don't see any rows because v-for seems does not find the elements, but the data object is not empty.

<script lang="ts">
import axios, {isCancel, AxiosError} from 'axios';
import { onMounted, reactive, VueElement } from 'vue';
import type { LanguagesTranslated } from './main';

var data: LanguagesTranslated = { translatedLanguages: [] };

onMounted(() => {
    axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => {
        console.log(response.request.response);
        data = JSON.parse(response.request.response);
        console.log(data.translatedLanguages);
    });
});
</script>

LanguagesTranslated is this interface:

export interface LanguagesTranslated {
    translatedLanguages: string[];
}
Comments:
2023-01-19 23:20:04
Thanks @jackssrt, I know the documentation.
2023-01-19 23:20:04
With script setup, unlike the option api, variables are not reactive by default. You have to use ref or reactive wrappers to make it reactive, so your template can react to their changes.
2023-01-19 23:20:04
You are not asking about <script setup> specifically, but the Composition API vs the Options API. Could you please edit your question?
Answers(1) :

Your first example is using the Options API. When using the Options API, properties in the object returned by data() are made reactive automatically.

The setup() function and <script setup> are the two ways of using the Composition API. When using the Composition API, your acts more like normal JavaScript. To create a reactive variable, you have to explicitly create it using one of the Reactivity API functions: ref(), reactive(), or computed().

As your example with <script setup> is creating a plain variable, it is not reactive and the v-for does not re-evaluate when you reassign it.

Try this:

<script setup lang="ts">
import axios, { isCancel, AxiosError } from 'axios';
import { ref, onMounted } from 'vue';
import type { LanguagesTranslated } from './main';

// Use `ref` here to create a Ref.
const data = ref<LanguagesTranslated>({ translatedLanguages: [] });

onMounted(() => {
    axios
        .get("https://translation.colreminder.com/test/data.php?request=langTranslated")
        .then(response => {
            console.log(response.request.response);
            // Use `data.value`, as `data` is a Ref.
            data.value = JSON.parse(response.request.response);
            console.log(data.value.translatedLanguages);
        });
});
</script>