Vue3 开发秘籍,封装一个超级好用的 Hook
共 4930字,需浏览 10分钟
·
2024-04-15 09:10
加入我们一起学习,天天进步
Vue3 的 Composition API 为我们提供了另一种代码组织方式,这个概念借鉴自 React 的 Hook。在 16.8 的版本中,React 引入了 React Hook,通过封装有状态的函数,提高了组件的编写效率和可维护性,在后面统一使用 Hook 来替代“组合式函数”。
Hook 允许我们将逻辑封装为可复用的函数,这些函数可以让你在组件之外管理状态和逻辑,从而在多个组件之间共享和复用。
封装自己的 Vue Hook
下面我们通过一个实际的业务场景来学习如何封装自己的 Vue Hook。我们将创建一个 useTable
Hook,它用于从 API 获取表格数据并支持分页。
基础版 useTable
Hook
首先,我们定义一个简单的 useTable
Hook,它通过调用 API 返回表格数据,并支持刷新。
// useTable.js
import { ref } from 'vue';
export function useTable(api) {
const data = ref([]);
const refresh = () => {
api().then(res => data.value = res);
};
refresh();
return [data, refresh];
}
支持分页查询
为了使 useTable
支持分页查询,我们需要对 API 进行改造,使其能够接受分页参数并返回分页数据。
// api.ts
export const getTableDataApi = (page, limit) => {
// ... 接口返回分页数据
}
然后,我们更新 useTable
Hook 以处理分页逻辑。
// const sizeOption = [10, 20, 50, 100, 200];
// useTable.js
import { reactive } from 'vue';
export function useTable(api, options) {
const pagination = reactive({
current: 1,
total: 0,
sizeOption,
size: sizeOption[0],
// ... 分页方法
});
// ... 刷新数据的逻辑
return [pagination, refresh];
}
处理 API 参数和加载状态
为了使 useTable
更加灵活,我们可以让 API 接受参数,并添加加载状态的管理。
// useTable.js
import { get } from "lodash-es";
export function useTable(api, options) {
const { path = {}, immediate = false } = options || {};
const { data: dataPath, total: totalPath, page: pagePath, size: sizePath } = path;
const [pagination, setPagination] = useState({
current: 1,
size: 10,
total: 0,
});
const [loading, setLoading] = useState(false);
const data = ref([]);
const refresh = async () => {
setLoading(true);
const { current, size } = pagination;
const res = await api({ [pagePath]: current, [sizePath]: size });
data.value = get(res, dataPath) || [];
setPagination(prevState => ({ ...prevState, total: get(res, totalPath) || 0 }));
setLoading(false);
};
useEffect(() => {
if (immediate) {
refresh();
}
}, [immediate]);
return { data, pagination, refresh, loading };
}
在这个版本中,useTable
Hook 接受一个 API 函数和一个选项对象,其中选项对象可以包含路径信息和是否立即刷新数据的标志。我们还添加了 loading
状态。
使用 useTable
Hook
在组件中,我们可以通过 useTable
Hook 的返回值来控制分页和数据加载。
<script setup>
import { useTable } from './useTable.js';
import { getTableDataApi } from './api.ts';
const { data, pagination, refresh, loading } = useTable(getTableDataApi, {
path: {
data: 'items',
total: 'totalCount',
page: 'currentPage',
size: 'pageSize'
},
immediate: true
});
</script>
<template>
<el-table :data="data" style="width: 100%">
<!-- 列定义 -->
</el-table>
<el-pagination
v-model:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
></el-pagination>
<button @click="refresh">Refresh</button>
<div v-if="loading">Loading...</div>
</template>
在这个例子中,我们使用 Element Plus 的表格和分页组件来展示 useTable
Hook 的功能。我们可以通过分页组件来改变当前页和每页大小,并使用 refresh
函数来手动刷新数据。
总结
我们学习了如何封装一个功能完善的 useTable
Hook,它不仅支持分页查询,还能够处理 API 参数和加载状态。这样的封装使得我们的代码可维护更高,同时也提高了开发效率。
最后不要忘了点赞和在看呦!
祝 2024 年暴富!暴美!暴瘦!