在从组合 API 创建的生命周期钩子中使用它

Mat*_*nar 3 typescript vue.js vuejs3

我在 Vue 3 中遇到打字稿问题。

  1. 每次修改 prop 'query' 时从 Itunes 获取数据。(格式: [{}, {},{},...]
  2. 调用函数从 fetch 中过滤未使用的信息

当我在 fetch 中调用函数(此函数将过滤对象以简化代码)时,它会抛出错误:

Property 'filterData' does not exist on type 'void'.
Run Code Online (Sandbox Code Playgroud)

我的代码:

<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>
Run Code Online (Sandbox Code Playgroud)

Mic*_*evý 6

我发现你的问题很有趣。

文档中可以清楚地看出,this不能在内部使用setup(),因为 Vue 实例尚不存在。

但在生命周期钩子的情况下,您要传递回调,该回调必须稍后附加到新的 Vue 实例

文档这些生命周期钩子注册函数只能在 期间同步使用setup(),因为它们依赖内部全局状态来定位当前活动实例(setup()当前正在调用的组件实例)。

因此,如果 Vue 只是使用回调并将其绑定到实例,那么正确的方法似乎会 很容易。bind然而事实似乎并非如此……

您的解决方案是filterDatamethods进入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 }
    }
Run Code Online (Sandbox Code Playgroud)

更新

我真的很好奇这背后的原因,因为我觉得钩子本质上与实例绑定在一起,并且可能很多人会期望this在回调中可用。所以我在 Vue Discord 上询问并收到了以下解释(感谢 Vaage#9161):

如果我们将 setup 中的生命周期钩子绑定到实例,它只会引起混乱并鼓励反模式。您可以做出选择,选项 api 或组合 api。如果您选择合成 api,那么 .NET 上没有什么让您感兴趣的this。一切都包含在setup闭包中。如果我们添加它,打字稿推理将更难实现,人们将开始将 options api 与它结合使用。

当天的消息

不要混合组合 api 和选项 api