hooks表格封装useTable

学习vue3之useTable封装

​ 在学习vue3中,极致的hook封装,业务与视图分离已经成为趋势。

​ 于是试着封装成适用于自己项目的通用型useTable,视图使用elementPlus的el-table和el-pagination,视图不做过多赘述。

1.开写代码之前需要先理清楚产物

由于项目是后台项目,主要有【查询区域】、【表格】、【分页】三部分组成,根据这三部分,可以梳理出如下产物

1.1 【查询区域】用到的查询参数变量searchParam

1.2 【查询区域】用到的查询方法 search()

1.3 【表格】要用到的数据变量 tableData

1.4 【分页】要用到的变量 pagination

1.5【分页】要用到pageSize变更方法 handleSizeChange()

1.6【分页】要用到currentPage变更方法 handleCurrentChange()

2.梳理出产物后,要能确保能实现上述的产物,接下来梳理入参

2.1 通用型hook,所以要有一个api的入参,确保每个业务都能试用

2.2 查询的时候有些查询条件会有默认值,于是需要一个initParam初始化查询参数的变量

2.3 比如java的mybatisPlus的分页和不分页的接口,返回的内容是不同的,于是加个isPageable参数控制是否需要分页,默认为true

2.4 有时候后端返回的数据,需要二次加工,加多个回调函数dataCallBack(data)

3.代码

export namespace Table {
	export interface Pagination {
		page: number;
		pageSize: number;
		total: number;
	}
	export interface TableStateProps {
		tableData: any[];
		pagination: Pagination;
		searchParam: {
			[key: string]: any;
		};
		searchInitParam: {
			[key: string]: any;
		};
		totalParam: {
			[key: string]: any;
		};
		icon?: {
			[key: string]: any;
		};
	}
}
import { reactive, onMounted, computed, toRefs } from 'vue'
import { Table } from "./interface";
/**
 * @description table 页面表格操作方法封装
 * @param {Function} api 获取表格数据 api 方法(必传)
 * @param {Object} initParam 获取数据初始化参数(非必传,默认为{})
 * @param {Boolean} isPageable 是否有分页(非必传,默认为true)
 * @param {Function} dataCallBack 对后台返回的数据进行处理的方法(非必传)
 * */
export const useTable = (
    api: (params: any) => Promise<any>,
    initParam: object = {},
    isPageable: boolean = true,
    dataCallBack?: (data: any) => any
) => {

    /**
     * 设计思路(首先要知道这个hook要输出的产物是什么?)
     * 产物:1.获取表格数据的方法getTableData
     * 产物:2.查询条件变量searchParam
     * 产物:3.分页查询条件变量pagination
     * 产物:4.分页pageSize变更的方法handleSizeChange()
     * 产物:5.分页currentPage变更的方法handleCurrentChange()
     * 产物:6.查询方法search()
     * 产物:7.初始化参数的变量searchInitParam
     */
    const state = reactive<Table.TableStateProps>({
        // 表格数据
        tableData: [],
        // 分页数据
        pagination: {
            // 当前页数
            page: 1,
            // 每页显示条数
            pageSize: 10,
            // 总条数
            total: 0
        },
        // 查询参数(只包括查询)
        searchParam: {},
        // 初始化默认的查询参数
        searchInitParam: {},
        // 总参数(包含分页和查询参数)
        totalParam: {}
    });
    const pageParam = computed({
        get: () => {
            return {
                page: state.pagination.page,
                pageSize: state.pagination.pageSize
            };
        },
        set: (newVal: any) => {
            console.log("我是分页更新之后的值", newVal);
        }
    });
    const getTableData = async () => {
        try {

            //合并查询参数
            Object.assign(state.totalParam, isPageable ? pageParam.value : {}, initParam)
            console.log(state.totalParam);

            let { data } = await api(state.totalParam)
            //回调处理,此处可以满足对特殊数据的处理
            dataCallBack && (data = dataCallBack(data))
            //根据是否分页,进行赋值
            state.tableData = isPageable ? data.records : data
            //对分页参数进行更新
            const { current: page, size: pageSize, total } = data;
            isPageable && updatePagination({ page, pageSize, total });
        } catch (err) {

        }
    }
    const updatePagination = (resPageable: Table.Pagination) => {
        Object.assign(state.pagination, resPageable);
    };
    const updatedTotalParam = () => {
        state.totalParam = {};
        // 处理查询参数,可以给查询参数加自定义前缀操作
        let nowSearchParam: { [key: string]: any } = {};
        // 防止手动清空输入框携带参数(这里可以自定义查询参数前缀)
        for (let key in state.searchParam) {
            // * 某些情况下参数为 false/0 也应该携带参数
            if (state.searchParam[key] || state.searchParam[key] === false || state.searchParam[key] === 0) {
                nowSearchParam[key] = state.searchParam[key];
            }
        }
        Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {});
    };

    const search = () => {
        state.pagination.page = 1;
        updatedTotalParam();
        getTableData();
    };

    const reset = () => {
        state.searchParam = {};
        // 重置搜索表单的时,如果有默认搜索参数,则重置默认的搜索参数
        Object.keys(state.searchInitParam).forEach(key => {
            state.searchParam[key] = state.searchInitParam[key];
        });
        search()
    };
    onMounted(() => {
        reset();
    });
    const handleSizeChange = (val: number) => {
        state.pagination.page = 1;
        state.pagination.pageSize = val;
        getTableData();
    };

    const handleCurrentChange = (val: number) => {
        state.pagination.page = val;
        getTableData();
    };

    return {
        ...toRefs(state),
        getTableData, handleCurrentChange, handleSizeChange, search, reset
    }


}

4.使用

const { getTableData, handleCurrentChange, handleSizeChange, tableData, pagination } = useTable(getArticleList, { pageSize: 5 })

4.1分页

 <el-pagination class="h-14 float-right clear-both mr-6" v-model:currentPage="pagination.page"
            :page-size="pagination.pageSize" layout="total, prev, pager, next" :total="pagination.total"
            @size-change="handleSizeChange" @current-change="handleCurrentChange">
        </el-pagination>

4.2表格

   <el-table :data="tableData" :show-header="false" class="px-6">
            <el-table-column prop="date" label="Date">
                <template #default="scope">
                    <div class="artcle" @click="artcleEvt(scope.row.id)">
                        <div class="text-lg text-black"> {{scope.row.title}}</div>
                        <div class="flex mt-2 text-gray-500">
                            <div class="ml-2">发布时间</div>
                            <div class="ml-2" v-show="scope.row.publishedTime"> {{scope.row.publishedTime.slice(0, 10)}}
                            </div>
                            <div class="ml-2 text-white px-2" v-show="scope.row.category"
                                style="backgroundColor:#0000ff;"> {{scope.row.category}}
                            </div>
                        </div>
                    </div>
                </template>
            </el-table-column>
        </el-table>
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 React Hooks 中,并没有内置的 useTable 方法。但是,你可以使用一些第三方库,如 react-table 或者 react-bootstrap-table-next,来实现一个功能强大的表格组件。 举例来说,如果你想使用 react-table,你可以按照以下步骤进行安装和使用: 1. 安装 react-table: ```bash npm install react-table ``` 2. 导入所需的组件和样式: ```jsx import React from "react"; import { useTable } from "react-table"; import "react-table/react-table.css"; ``` 3. 创建一个自定义的表格组件,并使用 useTable Hook 来处理数据和列的配置: ```jsx function MyTable({ columns, data }) { const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({ columns, data }); return ( <table {...getTableProps()} className="table"> <thead> {headerGroups.map(headerGroup => ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map(column => ( <th {...column.getHeaderProps()}>{column.render("Header")}</th> ))} </tr> ))} </thead> <tbody {...getTableBodyProps()}> {rows.map(row => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.cells.map(cell => ( <td {...cell.getCellProps()}>{cell.render("Cell")}</td> ))} </tr> ); })} </tbody> </table> ); } ``` 4. 在你的组件中使用 MyTable 组件,并传递列和数据的配置: ```jsx function App() { const columns = [ { Header: "Name", accessor: "name" }, { Header: "Age", accessor: "age" }, { Header: "Gender", accessor: "gender" } ]; const data = [ { name: "John Doe", age: 25, gender: "Male" }, { name: "Jane Smith", age: 30, gender: "Female" }, { name: "Bob Johnson", age: 40, gender: "Male" } ]; return ( <div className="App"> <MyTable columns={columns} data={data} /> </div> ); } ``` 在上述代码中,我们创建了一个自定义的表格组件 MyTable,并使用 useTable Hook 来处理列和数据的配置。我们使用了 react-table 提供的一些方法和属性来渲染表格的头部和主体部分。 这样,你就可以使用 react-table 和 useTable Hook 来创建一个功能完善的表格组件。同样的,你也可以根据你的需求选择其他类似的第三方库来实现表格功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值