Vue Hook 封裝通用型表格
一、創建通用型表格的需求
實現一個通用型表格組件,具備以下功能:
- 動態列配置。
- 分頁功能。
- 排序功能。
- 可擴展的行操作功能。
二、設計通用型表格組件
首先,需要設計一個基礎的表格組件,它接受列配置、數據和分頁信息等參數。
1. 創建 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, }; }
2. 創建 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>
三、使用通用型表格組件
在實際項目中,可以這樣使用這個通用型表格組件:
1. 創建 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>
四、解釋代碼
-
定義
useTableHook:- 使用 Vue 的
ref和reactive定義表格狀態。 - 定義
loadData、changePage、changePageSize和changeSort函數來處理數據加載和分頁、排序變化。 - 使用
onMounted生命周期鉤子在組件掛載時加載數據。
- 使用 Vue 的
-
定義
TableComponent組件:- 接受
fetchData和columns作為組件屬性。 - 使用
useTableHook 獲取表格數據和操作函數。 - 渲染表格頭部、主體和分頁組件,并綁定相關事件。
- 接受
-
使用通用型表格組件:
- 在
ExampleTable.vue中定義列配置和數據獲取函數。 - 使用
TableComponent并傳遞fetchData和columns屬性。
- 在

浙公網安備 33010602011771號