天天看點

Vue3 開發秘籍,封裝一個超級好用的 Hook

Vue3 開發秘籍,封裝一個超級好用的 Hook

Vue3 的 Composition API 為我們提供了另一種代碼組織方式,這個概念借鑒自 React 的 Hook。在 16.8 的版本中,React 引入了 React Hook,通過封裝有狀态的函數,提高了元件的編寫效率和可維護性,在後面統一使用 Hook 來替代“組合式函數”。

Hook 允許我們将邏輯封裝為可複用的函數,這些函數可以讓你在元件之外管理狀态和邏輯,進而在多個元件之間共享和複用。

封裝自己的 Vue Hook

下面我們通過一個實際的業務場景來學習如何封裝自己的 Vue Hook。我們将建立一個 useTable Hook,它用于從 API 擷取表格資料并支援分頁。

基礎版useTableHook

首先,我們定義一個簡單的 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 狀态。

使用useTableHook

在元件中,我們可以通過 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 參數和加載狀态。這樣的封裝使得我們的代碼可維護更高,同時也提高了開發效率。

繼續閱讀