typescript - Använda this i livscykelhaken created från compositions-API:et


Jag har ett problem med TypeScript i Vue 3.

  1. Hämta data från Itunes varje gång egenskapen 'query' ändras. (format: [{}, {}, {}, ...])
  2. Anropa funktion för att filtrera oanvänd information från hämtning

När jag anropar funktionen (denna funktion kommer att filtrera objekt för att förenkla koden) i fetch, kastar den ett fel:

Property 'filterData' does not exist on type 'void'.

Min kod:

<template>
    <div>
    </div>
</template>

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

interface Song {
    id: number;
    name: string;
    nameT: string;
    cover?: string;
    preview: string;
}

interface SongFromITunes {
    artistId: number;
    artistName: string;
    trackName: string;
    previewUrl: string;
    artworkUrl100?: string;
}

export default defineComponent({
    data() {
        return {
            list: [] as Array<Song>
        };
    },
    props: {
        query: String
    },
    methods: {
        filterData({
            artistId: id,
            artistName: name,
            trackName: nameT,
            artworkUrl100: cover,
            previewUrl: preview
        }: SongFromITunes): Song {
            return { id, name, nameT, cover, preview };
        }
    },
    setup(props) {
        onUpdated(() => {
            const { query } = props;
            if (query != null) {
                fetch(
                    `https://itunes.apple.com/search?term=${encodeURI(
                        query
                    )}&limit=10&entity=musicTrack`
                )
                    .then((resolve) => resolve.json())
                    .then((data) => data.results.map((item: SongFromITunes) => this.filterData(item));
            }
        });
    }
});
</script>

<style scoped></style>

Svar #1

Jag tyckte att din fråga var väldigt intressant.

Från dokumentationen är det klart att this inte kan användas inuti setup() eftersom Vue-instansen ännu inte existerar.

Men i fallet med livscykelhakar skickar du tillbaka anropet som måste senare fästas vid den nya Vue-instansen

Dokument : Dessa registreringsfunktioner för livscykelhakar kan endast användas synkront under setup(), eftersom de är beroende av intern global status för att hitta den aktuella aktiva instansen (komponentinstansen vars setup() som anropas just nu).

Så det verkar det rätta sättet att göra skulle vara det skulle vara enkelt om Vue bara använde bind och band tillbaka anropet till instansen. Men det verkar inte vara fallet...

Lösningen för dig är att flytta filterData från methods till setup()

    setup(props) {
        let filterData = function({
            artistId: id,
            artistName: name,
            trackName: nameT,
            artworkUrl100: cover,
            previewUrl: preview
        }: SongFromITunes): Song {
            return { id, name, nameT, cover, preview };
        }

        onUpdated(() => {
            const { query } = props;
            if (query != null) {
                fetch(
                    `https://itunes.apple.com/search?term=${encodeURI(
                        query
                    )}&limit=10&entity=musicTrack`
                )
                    .then((resolve) => resolve.json())
                    .then((data) => data.results.map((item: SongFromITunes) => filterData(item));
            }
        });

        return { filterData }
    }

Uppdatera

Jag var verkligen nyfiken på anledningarna bakom detta eftersom jag känner att hooks är inneboende bundna till instansen och förmodligen kommer många människor förvänta sig att this är tillgängligt i callbacks. Så jag frågade på Vue Discord och fick följande förklaring (tack Vaage#9161):

Om vi binder livscykelhakarna i setup till instansen skulle det bara orsaka förvirring och uppmuntra till dåliga mönster. Du måste göra ett val, options API eller composition API. Om du väljer composition API finns det inget intressant för dig på this. Allt finns i setup-slutningen. Om vi lade till det skulle TypeScripts inferens bli svårare att implementera, och folk skulle börja använda options API i kombination med det.

Dagens meddelande

Blanda inte composition API och options API

Svar #2

this är inte tillgängligt från setup-funktionen eftersom komponenten ännu inte har skapats. Du måste definiera filterData inuti setup också.

Här är den relevanta dokumentationen

Relaterade artiklar