首页/文章列表/文章详情

Vue Hook 封装通用型表格

编程知识1732024-08-01评论

一、创建通用型表格的需求

实现一个通用型表格组件,具备以下功能:

  1. 动态列配置。
  2. 分页功能。
  3. 排序功能。
  4. 可扩展的行操作功能。

二、设计通用型表格组件

首先,需要设计一个基础的表格组件,它接受列配置、数据和分页信息等参数。

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';exportdefault { 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';exportdefault { 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>

 

四、解释代码

  1. 定义useTableHook

    • 使用 Vue 的 refreactive定义表格状态。
    • 定义loadDatachangePagechangePageSizechangeSort函数来处理数据加载和分页、排序变化。
    • 使用onMounted生命周期钩子在组件挂载时加载数据。
  2. 定义TableComponent组件

    • 接受fetchDatacolumns作为组件属性。
    • 使用useTable Hook 获取表格数据和操作函数。
    • 渲染表格头部、主体和分页组件,并绑定相关事件。
  3. 使用通用型表格组件

    • ExampleTable.vue中定义列配置和数据获取函数。
    • 使用TableComponent并传递fetchDatacolumns属性。

 

博客园

这个人很懒...

用户评论 (0)

发表评论

captcha