#typescript #vue.js #vue-component #vuejs3
#typescript #vue.js #vue-компонент #vuejs3
Вопрос:
Я разрабатываю одностраничное приложение, используя Vue.js 3 и машинописный текст.
Проблема затрагивает представление и отдельный файловый компонент. People.vue
извлекает данные из серверной части и отображает их в нескольких PersonRow.vue
компонентах с использованием v-for
. Хотя типы свойств данных определены явно, я получаю предупреждение в консоли браузера:
[Vue warn]: Invalid prop: Type check failed for prop "person". Expected Person, got Object
Все работает нормально, и я мог бы изменить тип свойства на PersonRow.vue
Object
, чтобы избавиться от предупреждения, но я хотел бы, чтобы проверки типов работали правильно.
People.vue
<template>
<div class="container">
<PersonRow v-for="person in people" :key="person.id" :person="person" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { Person, getPeople } from '../services/person'
import PersonRow from '@/components/PersonRow.vue'
export default defineComponent({
components: {
PersonRow
},
data () {
return {
people: new Array<Person>()
}
},
mounted () {
getPeople().then(
response => {
this.people.push(...response)
})
}
})
</script>
PersonRow.vue
<template>
<div class="row">
<div class="col">{{ person.givenName }}</div>
<div class="col">{{ person.familyName }}</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { Person } from '../services/person'
export default defineComponent({
props: {
person: {
type: Person,
required: true
}
}
})
</script>
person.ts
export class Person {
constructor (id: number, givenName: string, familyName: string) {
this.id = id
this.givenName = givenName
this.familyName = familyName
}
id: number;
givenName: string;
familyName: string;
}
export async function getPeople (): Promise<Person[]> {
const response = await fetch('https://api.example.com/people')
return await response.json() as Person[]
}
Ответ №1:
export default defineComponent({
props: {
person: {
type: Object as PropType<Person>,
required: true
}
}
})
Более глубокое погружение
Да, в документах говорится: кроме того, type
также может быть пользовательская функция конструктора, и утверждение будет выполнено с instanceof
проверкой
Но для того, чтобы заставить его работать, объект, переданный в prop, должен быть создан с new Person()
помощью constructor . И проблема в том, что ваша getPeople ()
функция не создает массив Person
экземпляров — это просто массив приведения типов обычных объектов JS, созданных с json()
помощью to Person[]
. Приведение к типу не изменяет тип объекта во время выполнения…
Комментарии:
1. Обратите внимание, что вам, возможно, придется
import type { PropType } from 'vue'
использоватьPropType
Ответ №2:
«Person» не является типом. Типами могут быть массив, объект, строка, число, логическое значение, функция. Таким образом, проверки типов работают правильно.
Комментарии:
1. В документах указано, что возможны пользовательские типы: v3.vuejs.org/guide/component-props.html#type-checks
2. Но они означают классы JavaScript. Если ваш класс TypeScript переносится во время сборки, для Vue это просто объект во время выполнения (когда происходит проверка типа prop)
3. Также в документах говорится, что проверяется, что значение
author
реквизита было создано сnew Person
помощью, но вашаgetPeople
функция не вызываетPerson
конструктор, это просто приведение обычных объектов JS, десериализованных из JSON вPerson[]
4. Спасибо, что упомянули об этом.
PropType<T>
позволило мне изменить мое определение типа сclass
наinterface
, что устраняет все накладные расходы на неиспользуемые конструкторы, пока вывод и проверка типов все еще работают.