实现一个通用型表格组件,具备以下功能:
首先,需要设计一个基础的表格组件,它接受列配置、数据和分页信息等参数。
useTable
Hook在 src/hooks
目录下创建 useTable.js
文件:
import { ref, reactive, onMounted, toRefs } from 'vue'; export function useTable(fetchData) { const state = reactive({ loading: false, data: [], pagination: { currentPage: 1, pageSize: 10, total: 0, }, sort: { field: '', order: '', }, }); const loadData = async () => { state.loading = true; const { currentPage, pageSize } = state.pagination; const { field, order } = state.sort; const result = await fetchData(currentPage, pageSize, field, order); state.data = result.data; state.pagination.total = result.total; state.loading = false; }; const changePage = (page) => { state.pagination.currentPage = page; loadData(); }; const changePageSize = (size) => { state.pagination.pageSize = size; loadData(); }; const changeSort = (field, order) => { state.sort.field = field; state.sort.order = order; loadData(); }; onMounted(() => { loadData(); }); return { ...toRefs(state), loadData, changePage, changePageSize, changeSort, }; }
TableComponent.vue
在 src/components
目录下创建 TableComponent.vue
文件:
<template> <div> <table> <thead> <tr> <th v-for="col in columns" :key="col.key" @click="changeSort(col.key)"> {{ col.title }} <span v-if="sort.field === col.key">{{ sort.order === 'asc' ? '↑' : '↓' }}</span> </th> </tr> </thead> <tbody> <tr v-for="row in data" :key="row.id"> <td v-for="col in columns" :key="col.key">{{ row[col.key] }}</td> </tr> </tbody> </table> <div class="pagination"> <button @click="changePage(pagination.currentPage - 1)" :disabled="pagination.currentPage === 1">Previous</button> <span>{{ pagination.currentPage }} / {{ Math.ceil(pagination.total / pagination.pageSize) }}</span> <button @click="changePage(pagination.currentPage + 1)" :disabled="pagination.currentPage === Math.ceil(pagination.total / pagination.pageSize)">Next</button> </div> </div> </template> <script> import { ref, onMounted } from 'vue'; import { useTable } from '@/hooks/useTable'; export default { props: { fetchData: { type: Function, required: true, }, columns: { type: Array, required: true, }, }, setup(props) { const { data, loading, pagination, sort, loadData, changePage, changePageSize, changeSort } = useTable(props.fetchData); return { data, loading, pagination, sort, loadData, changePage, changePageSize, changeSort, }; }, }; </script> <style scoped> .pagination { display: flex; justify-content: center; margin-top: 10px; } </style>
在实际项目中,可以这样使用这个通用型表格组件:
ExampleTable.vue
组件在 src/views
目录下创建 ExampleTable.vue
文件:
<template> <div> <TableComponent :fetchData="fetchData" :columns="columns" /> </div> </template> <script> import TableComponent from '@/components/TableComponent.vue'; export default { components: { TableComponent, }, setup() { const columns = [ { key: 'name', title: 'Name' }, { key: 'age', title: 'Age' }, { key: 'email', title: 'Email' }, ]; const fetchData = async (page, pageSize, sortField, sortOrder) => { // 模拟数据获取 const total = 100; const data = Array.from({ length: pageSize }, (v, i) => ({ id: (page - 1) * pageSize + i + 1, name: `Name ${(page - 1) * pageSize + i + 1}`, age: 20 + ((page - 1) * pageSize + i + 1) % 30, email: `user${(page - 1) * pageSize + i + 1}@example.com`, })); return { data, total }; }; return { columns, fetchData, }; }, }; </script>
定义 useTable
Hook:
ref
和 reactive
定义表格状态。loadData
、changePage
、changePageSize
和 changeSort
函数来处理数据加载和分页、排序变化。onMounted
生命周期钩子在组件挂载时加载数据。定义 TableComponent
组件:
fetchData
和 columns
作为组件属性。useTable
Hook 获取表格数据和操作函数。使用通用型表格组件:
ExampleTable.vue
中定义列配置和数据获取函数。TableComponent
并传递 fetchData
和 columns
属性。