Recientemente comencé con Vue 3 y Headless UI.
Creé un componente ListBox que se usa en App.vue para mostrar una lista de People y funciona según lo previsto.
Estoy buscando convertirlo en un componente reutilizable para mostrar listas de People y Countries .
¿Cómo puedo cambiar mi componente para que sea dinámico para ambos tipos?
ListBox.vue
<template> <Listbox v-model="selectedPerson"> <ListboxButton class=" bg-white shadow-sm border-gray-500 border-2 shadow-gray-200 font-bold p-4 text-left rounded-md"> {{ selectedPerson.name }} </ListboxButton> <ListboxOptions class="mt-2"> <ListboxOption as="template" v-slot="{ active }" v-for="person in people" :key="person" :value="person"> <li :class="{ 'bg-blue-500 text-white p-6': active, 'bg-white shadow-lg p-6 text-black ': !active }"> {{ person.name }} </li> </ListboxOption> </ListboxOptions> </Listbox> </template> <script setup> import { ref } from 'vue' import { Listbox, ListboxLabel, ListboxButton, ListboxOptions, ListboxOption, } from '@headlessui/vue' const people = [ { id: 1, name: 'Durward Reynolds' }, { id: 2, name: 'Kenton Towne' }, { id: 3, name: 'Therese Wunsch' }, { id: 4, name: 'Benedict Kessler' }, { id: 5, name: 'Katelyn Rohan' }, ] const selectedPerson = ref(people[0]) </script>Aplicación.vue:
<template> <ListBox /> </template>Deberá aceptar tanto la lista de elementos para mostrar como el elemento seleccionado actualmente o el índice de la lista como accesorios en el componente.
El siguiente es un ejemplo, codificado sobre la marcha y no probado, pero debería darle una idea clara de qué probar y cómo proceder.
También cambiaría el nombre del componente para evitar confusiones con el componente Listbox que está utilizando desde Headless UI.
aplicación.vue
<template> <ItemList :items='people' :selected-index='0' /> <ItemList :items='countries' :selected-index='0' /> </template> <script> const people = [ { id: 1, name: 'Durward Reynolds' }, { id: 2, name: 'Kenton Towne' }, { id: 3, name: 'Therese Wunsch' }, { id: 4, name: 'Benedict Kessler' }, { id: 5, name: 'Katelyn Rohan' }, ] const countries = [ { id: 1, name: 'Italy' }, { id: 2, name: 'Switzerland' }, { id: 3, name: 'Austria' }, { id: 4, name: 'Germany' }, ] </script>ItemList.vue
<template> <Listbox v-model="selectedItem"> <ListboxButton class=" bg-white shadow-sm border-gray-500 border-2 shadow-gray-200 font-bold p-4 text-left rounded-md"> {{ selectedItem.name }} </ListboxButton> <ListboxOptions class="mt-2"> <ListboxOption as="template" v-slot="{ active }" v-for="item in items" :key="item.id" :value="item"> <li :class="{ 'bg-blue-500 text-white p-6': active, 'bg-white shadow-lg p-6 text-black ': !active }"> {{ item.name }} </li> </ListboxOption> </ListboxOptions> </Listbox> </template> <script setup> import { ref, onMounted } from 'vue' import { Listbox, ListboxLabel, ListboxButton, ListboxOptions, ListboxOption, } from '@headlessui/vue' const props = defineProps({ items: Array, selectedIndex: Number, }) const selectedItem = ref(null) onMounted(() => { if(items && selectedIndex >= 0 && selectedIndex < items.length) { selectedItem.value = items[selectedIndex] } }) </script>Casi hiciste lo que querías, lo único que necesitas son props .
Las people y los countries son instancias de su componente secundario DataTable.vue y desea usarlos en un componente principal App.vue .
DataTable.vue:
<template> <div id='data-table'> {{table}} </div> </template> <script> export default { . . . props: ['table'] } </script>Aplicación.vue:
<template> <data-table table='people' /> <data-table table='countries' /> </template> Y también tiene que definir las tablas fuera del componente secundario y luego pasarlas al componente secundario, la mejor manera de hacerlo es usar state management como vuex