#typescript #vue.js #vuejs3
#typescript #vue.js #vuejs3
Вопрос:
У меня проблема с typescript в Vue 3.
- Получайте данные из Itunes каждый раз, когда изменяется prop ‘query’. (формат: [{}, {},{},…]
- Вызовите функцию для фильтрации неиспользуемой информации из выборки
Когда я вызываю функцию (эта функция будет фильтровать объекты для упрощения кода) в fetch, она выдает ошибку:
Property 'filterData' does not exist on type 'void'.
Мой код:
<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
)}amp;limit=10amp;entity=musicTrack`
)
.then((resolve) => resolve.json())
.then((data) => data.results.map((item: SongFromITunes) => this.filterData(item));
}
});
}
});
</script>
<style scoped></style>
Ответ №1:
Я нашел ваш вопрос действительно интересным.
Из документов ясно this
, что его нельзя использовать внутри setup()
, поскольку экземпляр Vue еще не существует.
Но в случае перехватов жизненного цикла вы передаете обратный вызов, который должен быть через некоторое время присоединен к новому экземпляру Vue
Документы: Эти функции регистрации цепочек жизненного цикла могут использоваться только синхронно во setup()
время, поскольку они полагаются на внутреннее глобальное состояние для определения местоположения текущего активного экземпляра (экземпляра компонента, который setup()
вызывается прямо сейчас).
Таким образом, кажется, что правильный способ сделать это было бы легко, если бы Vue просто использовал bind
и привязал обратный вызов к экземпляру. Однако, похоже, это не так…
Решение для вас — перейти filterData
из methods
в 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
)}amp;limit=10amp;entity=musicTrack`
)
.then((resolve) => resolve.json())
.then((data) => data.results.map((item: SongFromITunes) => filterData(item));
}
});
return { filterData }
}
Обновить
Мне было действительно любопытно узнать о причинах этого, потому что я чувствую, что крючки по своей сути привязаны к экземпляру, и, вероятно, многие люди ожидают this
, что он доступен в обратных вызовах. Итак, я спросил о Vue discord и получил следующее объяснение (спасибо Vaage # 9161):
Если мы привяжем крючки жизненного цикла в setup к экземпляру, это только вызовет путаницу и вызовет антипаттерны. Вы делаете выбор, api опций или composition api. Если вы выберете composition api, для вас не будет ничего интересного this
. Все содержится в setup
закрытии. Если бы мы добавили его, вывод typescript было бы сложнее реализовать, и люди начнут использовать options api в сочетании с ним.
Сообщение дня
Не смешивайте composition api и options api
Комментарии:
1. «Сообщение дня»: точно, решите, что использовать в проекте, и придерживайтесь его!
Ответ №2:
this
недоступен из функции настройки, поскольку компонент еще не создан. Вам также необходимо определить filterData
внутреннюю настройку.