Generic компоненты в Quasar Framework позволяют создавать переиспользуемые, параметризованные элементы интерфейса, которые могут работать с разными типами данных и конфигурациями. Такой подход повышает гибкость приложений и уменьшает дублирование кода.
Generic компонент в Quasar создаётся как стандартный Vue-компонент с использованием TypeScript для определения типов входных данных. Это позволяет использовать сильную типизацию и получать автодополнение при разработке.
Пример базового Generic компонента:
<script lang="ts" setup>
import { defineProps } from 'vue'
interface Item {
id: number
name: string
}
const props = defineProps<{ items: Item[] }>()
</script>
<template>
<q-list bordered padding>
<q-item v-for="item in props.items" :key="item.id">
<q-item-section>{{ item.name }}</q-item-section>
</q-item>
</q-list>
</template>
В этом примере компонент принимает массив элементов типа
Item. Можно расширить этот компонент, сделав его Generic,
чтобы он принимал любой тип данных:
<script lang="ts" setup>
import { defineProps } from 'vue'
type GenericProps<T> = {
items: T[]
displayField: keyof T
}
const props = defineProps<GenericProps<any>>()
</script>
<template>
<q-list bordered padding>
<q-item v-for="item in props.items" :key="item[props.displayField]">
<q-item-section>{{ item[props.displayField] }}</q-item-section>
</q-item>
</q-list>
</template>
Теперь компонент можно использовать с любым типом объектов, указывая поле, которое нужно отображать.
Generic компоненты особенно полезны при работе со слотами, где необходимо передавать пользовательские шаблоны отображения. Например:
<script lang="ts" setup>
import { defineProps, type PropType } from 'vue'
type GenericProps<T> = {
items: T[]
}
const props = defineProps<GenericProps<any>>()
</script>
<template>
<q-list bordered padding>
<slot name="item" v-for="item in props.items" :item="item" :key="item.id">
<q-item>
<q-item-section>{{ item.name }}</q-item-section>
</q-item>
</slot>
</q-list>
</template>
Использование компонента с кастомным шаблоном:
<GenericList :items="users">
<template #item="{ item }">
<q-item>
<q-item-section>{{ item.fullName }}</q-item-section>
<q-item-section side>{{ item.age }}</q-item-section>
</q-item>
</template>
</GenericList>
Это позволяет полностью контролировать отображение данных без изменения внутренней логики компонента.
TypeScript обеспечивает строгую типизацию Generic компонентов,
предотвращая ошибки при передаче данных. Определение типа через
PropType<T> делает компонент максимально гибким и
безопасным:
import { PropType } from 'vue'
interface User {
id: number
name: string
email: string
}
const props = defineProps({
items: {
type: Array as PropType<User[]>,
required: true
}
})
Для Generic компонента можно использовать параметр типа
T:
const props = defineProps<{ items: T[] }>()
Вместе с emit и событиями это позволяет создавать компоненты, которые работают с любым типом данных и возвращают строго типизированные события.
Generic форма с q-input и q-select:
<script lang="ts" setup>
import { defineProps } from 'vue'
type Field<T> = {
label: string
model: keyof T
type: 'text' | 'number' | 'select'
options?: T[]
}
interface GenericFormProps<T> {
data: T
fields: Field<T>[]
}
const props = defineProps<GenericFormProps<any>>()
</script>
<template>
<q-form>
<q-input v-for="field in props.fields"
v-if="field.type === 'text'"
:key="field.model"
v-model="props.data[field.model]"
:label="field.label" />
<q-select v-for="field in props.fields"
v-if="field.type === 'select'"
:key="field.model"
v-model="props.data[field.model]"
:options="field.options"
:label="field.label" />
</q-form>
</template>
Такой подход позволяет строить динамические формы, где структура и типы данных полностью управляются внешними параметрами.
key) для оптимизации рендеринга Vue и корректной работы
виртуального DOM.Generic компоненты являются основой масштабируемого и типобезопасного фронтенда на Quasar Framework, позволяя строить сложные интерфейсы с минимальными усилиями и высокой переиспользуемостью кода.