diff --git a/src/api/hook-demo/use-fetch-select.ts b/src/api/hook-demo/use-fetch-select.ts
new file mode 100644
index 0000000..5998e40
--- /dev/null
+++ b/src/api/hook-demo/use-fetch-select.ts
@@ -0,0 +1,36 @@
+/** 模拟接口响应数据 */
+const SELECT_DATA = {
+  code: 0,
+  data: [
+    {
+      label: "苹果",
+      value: 1
+    },
+    {
+      label: "香蕉",
+      value: 2
+    },
+    {
+      label: "橘子",
+      value: 3,
+      disabled: true
+    }
+  ],
+  message: "获取 Select 数据成功"
+}
+
+/** 模拟接口 */
+export function getSelectDataApi() {
+  return new Promise<typeof SELECT_DATA>((resolve, reject) => {
+    // 模拟接口响应时间 2s
+    setTimeout(() => {
+      // 模拟接口调用成功
+      if (Math.random() < 0.8) {
+        resolve(SELECT_DATA)
+      } else {
+        // 模拟接口调用出错
+        reject(new Error("接口发生错误"))
+      }
+    }, 2000)
+  })
+}
diff --git a/src/api/hook-demo/use-fullscreen-loading.ts b/src/api/hook-demo/use-fullscreen-loading.ts
new file mode 100644
index 0000000..6f86104
--- /dev/null
+++ b/src/api/hook-demo/use-fullscreen-loading.ts
@@ -0,0 +1,24 @@
+/** 模拟接口响应数据 */
+const SUCCESS_DATA = {
+  code: 0,
+  data: {},
+  message: "获取成功"
+}
+
+/** 模拟请求接口成功 */
+export function getSuccessApi() {
+  return new Promise<typeof SUCCESS_DATA>((resolve) => {
+    setTimeout(() => {
+      resolve(SUCCESS_DATA)
+    }, 1000)
+  })
+}
+
+/** 模拟请求接口失败 */
+export function getErrorApi() {
+  return new Promise((_resolve, reject) => {
+    setTimeout(() => {
+      reject(new Error("发生错误"))
+    }, 1000)
+  })
+}
diff --git a/src/api/mock.ts b/src/api/mock.ts
deleted file mode 100644
index d16c594..0000000
--- a/src/api/mock.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-export function getRemoteSelectData() {
-  return new Promise<any>((resolve, reject) => {
-    setTimeout(() => {
-      // 模拟接口调用有概率出错
-      if (Math.random() > 0.5) {
-        resolve({
-          code: 0,
-          data: [
-            {
-              key: 1,
-              label: "苹果",
-              value: 1
-            },
-            {
-              key: 2,
-              label: "香蕉",
-              value: 2
-            },
-            {
-              key: 3,
-              label: "橘子",
-              value: 3
-            }
-          ],
-          message: "成功"
-        })
-      } else {
-        reject(new Error("不小心出错了!"))
-      }
-    }, 3000)
-  })
-}
-
-export interface IComicsItem {
-  id: number
-  name: string
-}
-
-export const getComics = () => {
-  return new Promise<IComicsItem[]>((resolve) => {
-    setTimeout(() => {
-      resolve([...Array(5)].map((_t, index) => ({ id: index, name: `c${index}` })))
-    }, 1000)
-  })
-}
-
-export const getAnimations = (id: number) => {
-  return new Promise((_resolve, reject) => {
-    setTimeout(() => {
-      reject(new Error(`Sorry, there is an error here. The error id is ${id}`))
-    }, 1000)
-  })
-}
diff --git a/src/hooks/useFetchSelect.ts b/src/hooks/useFetchSelect.ts
index d3812cf..02c623c 100644
--- a/src/hooks/useFetchSelect.ts
+++ b/src/hooks/useFetchSelect.ts
@@ -1,51 +1,44 @@
-import { onMounted, ref } from "vue"
+import { ref, onMounted } from "vue"
 
-// 定义下拉框接收的数据格式
-export interface SelectOption {
-  value: string
+type OptionValueType = string | number
+
+/** Select 需要的数据格式 */
+interface ISelectOption {
+  value: OptionValueType
   label: string
   disabled?: boolean
-  key?: string
 }
 
-// 定义入参格式
-interface FetchSelectProps {
-  apiFun: () => Promise<any>
+/** 接口响应格式 */
+interface IApiData {
+  code: number
+  data: ISelectOption[]
+  message: string
 }
 
-export function useFetchSelect(props: FetchSelectProps) {
-  const { apiFun } = props
+/** 入参格式,暂时只需要传递 api 函数即可 */
+interface IFetchSelectProps {
+  api: () => Promise<IApiData>
+}
 
-  const options = ref<SelectOption[]>([])
+export function useFetchSelect(props: IFetchSelectProps) {
+  const { api } = props
 
-  const loading = ref(false)
+  const loading = ref<boolean>(false)
+  const options = ref<ISelectOption[]>([])
+  const value = ref<OptionValueType>("")
 
-  const selectedValue = ref("")
-
-  /* 调用接口请求数据 */
+  /** 调用接口获取数据 */
   const loadData = () => {
     loading.value = true
     options.value = []
-    return apiFun().then(
-      (res) => {
-        loading.value = false
+    api()
+      .then((res) => {
         options.value = res.data
-        return res.data
-      },
-      (err) => {
-        // 未知错误,可能是代码抛出的错误,或是网络错误
+      })
+      .finally(() => {
         loading.value = false
-        options.value = [
-          {
-            value: "-1",
-            label: err.message,
-            disabled: true
-          }
-        ]
-        // 接着抛出错误
-        return Promise.reject(err)
-      }
-    )
+      })
   }
 
   onMounted(() => {
@@ -53,8 +46,8 @@ export function useFetchSelect(props: FetchSelectProps) {
   })
 
   return {
-    options,
     loading,
-    selectedValue
+    options,
+    value
   }
 }
diff --git a/src/hooks/useFullscreenLoading.ts b/src/hooks/useFullscreenLoading.ts
index 64e14f9..46d810c 100644
--- a/src/hooks/useFullscreenLoading.ts
+++ b/src/hooks/useFullscreenLoading.ts
@@ -1,53 +1,53 @@
-import { ElLoading, LoadingOptions } from "element-plus"
+import { type LoadingOptions, ElLoading } from "element-plus"
 
-const defaultOption = {
+const defaultOptions = {
   lock: true,
-  text: "加载中...",
-  background: "rgba(0, 0, 0, 0.7)"
+  text: "加载中..."
 }
 
-interface ILoading {
+interface ILoadingInstance {
   close: () => void
 }
 
 /**
- * 传入一个方法 fn,在它执行周期内,加上「全屏」loading
+ * 传入一个函数 fn,在它执行周期内,加上「全屏」loading,
  * 如果:
- * 1. fn 是同步方法,结束后隐藏 loading
- * 2. 如果是异步方法,resolve 后隐藏 loading
+ * 1. fn 如果是同步函数,执行结束后隐藏 loading
+ * 2. fn 如果是 Promise,resolve 或 reject 后隐藏 loading
  * 3. 报错后隐藏 loading 并抛出错误
  * @param {*} fn 函数
- * @param options
+ * @param options LoadingOptions
  * @returns Function 一个新的函数,去执行它吧
  */
-export const useFullscreenLoading = <T>(
-  fn: (...args: any[]) => T,
+export function useFullscreenLoading<T>(
+  fn: (...args: any[]) => T | Promise<T>,
   options: LoadingOptions = {}
-): ((...args: any[]) => Promise<T>) => {
-  let loading: ILoading | undefined
+): (...args: any[]) => Promise<T> {
+  let loadingInstance: ILoadingInstance
   const showLoading = (options: LoadingOptions) => {
-    loading = ElLoading.service(options)
+    loadingInstance = ElLoading.service(options)
   }
-
   const hideLoading = () => {
-    loading && loading.close()
+    loadingInstance && loadingInstance.close()
   }
-  const _options = { ...defaultOption, ...options }
-  const newFn = (...args: any[]) => {
+  const _options = { ...defaultOptions, ...options }
+  return (...args: any[]) => {
     try {
       showLoading(_options)
       const result = fn(...args)
       const isPromise = result instanceof Promise
+      // 同步函数
       if (!isPromise) {
         hideLoading()
         return Promise.resolve(result)
       }
+      // Promise
       return result
-        .then((res: any) => {
+        .then((res) => {
           hideLoading()
           return res
         })
-        .catch((err: Error) => {
+        .catch((err) => {
           hideLoading()
           throw err
         })
@@ -56,5 +56,4 @@ export const useFullscreenLoading = <T>(
       throw err
     }
   }
-  return newFn
 }
diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts
index 9edd1f3..d860884 100644
--- a/src/hooks/usePagination.ts
+++ b/src/hooks/usePagination.ts
@@ -25,7 +25,7 @@ const defaultPaginationData: IDefaultPaginationData = {
   layout: "total, sizes, prev, pager, next, jumper"
 }
 
-export const usePagination = (_paginationData: IPaginationData = {}) => {
+export function usePagination(_paginationData: IPaginationData = {}) {
   /** 合并分页参数 */
   const paginationData = reactive(Object.assign({ ...defaultPaginationData }, _paginationData))
 
diff --git a/src/router/index.ts b/src/router/index.ts
index ba71697..e5d4c73 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -190,19 +190,19 @@ export const constantRoutes: RouteRecordRaw[] = [
     ]
   },
   {
-    path: "/hooks",
+    path: "/hook-demo",
     component: Layout,
-    redirect: "/hooks/use-fetch-select",
-    name: "Hooks",
+    redirect: "/hook-demo/use-fetch-select",
+    name: "HookDemo",
     meta: {
-      title: "hooks",
+      title: "hook 示例",
       elIcon: "Menu",
       alwaysShow: true
     },
     children: [
       {
         path: "use-fetch-select",
-        component: () => import("@/views/hooks/use-fetch-select.vue"),
+        component: () => import("@/views/hook-demo/use-fetch-select.vue"),
         name: "UseFetchSelect",
         meta: {
           title: "useFetchSelect"
@@ -210,7 +210,7 @@ export const constantRoutes: RouteRecordRaw[] = [
       },
       {
         path: "use-fullscreen-loading",
-        component: () => import("@/views/hooks/use-fullscreen-loading.vue"),
+        component: () => import("@/views/hook-demo/use-fullscreen-loading.vue"),
         name: "UseFullscreenLoading",
         meta: {
           title: "useFullscreenLoading"
diff --git a/src/views/hook-demo/use-fetch-select.vue b/src/views/hook-demo/use-fetch-select.vue
new file mode 100644
index 0000000..ecf144c
--- /dev/null
+++ b/src/views/hook-demo/use-fetch-select.vue
@@ -0,0 +1,20 @@
+<script lang="ts" setup>
+import { useFetchSelect } from "@/hooks/useFetchSelect"
+import { getSelectDataApi } from "@/api/hook-demo/use-fetch-select"
+
+const { loading, options, value } = useFetchSelect({
+  api: getSelectDataApi
+})
+</script>
+
+<template>
+  <div class="app-container">
+    <h4>该示例是演示:通过 hook 自动调用 api 后拿到 Select 组件需要的数据并传递给 Select 组件</h4>
+    <h5>Select 示例</h5>
+    <el-select :loading="loading" v-model="value" filterable>
+      <el-option v-for="(item, index) in options" v-bind="item" :key="index" placeholder="请选择" />
+    </el-select>
+    <h5>Select V2 示例(如果数据量过多,可以选择该组件)</h5>
+    <el-select-v2 :loading="loading" v-model="value" :options="options" filterable placeholder="请选择" />
+  </div>
+</template>
diff --git a/src/views/hook-demo/use-fullscreen-loading.vue b/src/views/hook-demo/use-fullscreen-loading.vue
new file mode 100644
index 0000000..460444a
--- /dev/null
+++ b/src/views/hook-demo/use-fullscreen-loading.vue
@@ -0,0 +1,44 @@
+<script lang="ts" setup>
+import { useFullscreenLoading } from "@/hooks/useFullscreenLoading"
+import { getSuccessApi, getErrorApi } from "@/api/hook-demo/use-fullscreen-loading"
+import { ElMessage } from "element-plus"
+
+const svg = `
+  <path class="path" d="
+    M 30 15
+    L 28 17
+    M 25.61 25.61
+    A 15 15, 0, 0, 1, 15 30
+    A 15 15, 0, 1, 1, 27.99 7.5
+    L 15 15
+  " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
+`
+
+const options = {
+  text: "即将发生错误...",
+  background: "#F56C6C20",
+  svg,
+  svgViewBox: "-10, -10, 50, 50"
+}
+
+const querySuccess = async () => {
+  const res = await useFullscreenLoading(getSuccessApi)()
+  ElMessage.success(res.message)
+}
+
+const queryError = async () => {
+  try {
+    await useFullscreenLoading(getErrorApi, options)()
+  } catch (err: any) {
+    ElMessage.error(err.message)
+  }
+}
+</script>
+
+<template>
+  <div class="app-container">
+    <h4>该示例是演示:通过将要执行的函数传递给 hook,让 hook 自动开启全屏 loading,函数执行结束后自动关闭 loading</h4>
+    <el-button @click="querySuccess">查询成功</el-button>
+    <el-button @click="queryError">查询失败</el-button>
+  </div>
+</template>
diff --git a/src/views/hooks/use-fetch-select.vue b/src/views/hooks/use-fetch-select.vue
deleted file mode 100644
index f8f9467..0000000
--- a/src/views/hooks/use-fetch-select.vue
+++ /dev/null
@@ -1,18 +0,0 @@
-<script setup name="Select" lang="ts">
-import { getRemoteSelectData } from "@/api/mock"
-import { useFetchSelect } from "@/hooks/useFetchSelect"
-
-const { loading, options, selectedValue } = useFetchSelect({
-  apiFun: getRemoteSelectData
-})
-</script>
-
-<template>
-  <div class="app-container">
-    <el-select :loading="loading" v-model="selectedValue">
-      <el-option v-for="(item, index) in options" v-bind="item" :key="index" />
-    </el-select>
-    <span class="m-x">Select V2 示例</span>
-    <el-select-v2 :loading="loading" v-model="selectedValue" :options="options" />
-  </div>
-</template>
diff --git a/src/views/hooks/use-fullscreen-loading.vue b/src/views/hooks/use-fullscreen-loading.vue
deleted file mode 100644
index a8958aa..0000000
--- a/src/views/hooks/use-fullscreen-loading.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-<template>
-  <div class="app-container">
-    <el-button @click="querySuccess">查询成功</el-button>
-    <el-button @click="queryFailed">查询失败</el-button>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { getComics, getAnimations, type IComicsItem } from "@/api/mock"
-import { useFullscreenLoading } from "@/hooks/useFullscreenLoading"
-import { ElMessage } from "element-plus"
-
-const querySuccess = async () => {
-  const comics = await useFullscreenLoading(getComics)()
-  ElMessage.success("Successfully get comics: " + comics.map((t: IComicsItem) => t.name).join())
-}
-
-const svg = `
-  <path class="path" d="
-    M 30 15
-    L 28 17
-    M 25.61 25.61
-    A 15 15, 0, 0, 1, 15 30
-    A 15 15, 0, 1, 1, 27.99 7.5
-    L 15 15
-  " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
-`
-
-const queryFailed = async () => {
-  try {
-    await useFullscreenLoading(getAnimations, {
-      text: "自定义加载文字",
-      background: "rgba(255, 214, 210, 0.7)",
-      svg,
-      svgViewBox: "-10, -10, 50, 50"
-    })(233)
-  } catch (err: any) {
-    ElMessage.error(err.message)
-  }
-}
-</script>