vue3封装Hooks实现更好的逻辑复用过程

 更新时间:2026年07月10日 10:36:17   作者:sulli_la  
别再复制粘贴表格逻辑了!学会Vue3的useTable Hooks,轻松复用增删查改和分页功能,本文从鼠标跟踪案例入手,手把手教你封装组合式函数,解决DataV组件自适应问题,并用TypeScript实现可复用的表格数据请求逻辑,提升代码可维护性

在构建前端应用中,经常会需要复用公共任务的逻辑。例如在一个管理后台中会存在很多的表格,其中的增删查改的内容就是可复用的部分,我们在写页面的过程中如果不封装的话会发现我们经常复制/粘贴。

在Vue3的Composition API中引入了Hooks的概念,为我们提供了更灵活和可组合的代码组织方式。其中的一个重要概念就是Hooks。

Hooks是一种函数,以use开头,用于封装一些可复用的逻辑。它们提供了一种在函数组件中复用状态逻辑的方式,使我们能够更好地组织组件代码,将相关的逻辑聚合在一起,实现更高水平的可维护性。

Vue3官网的案例分析

在vue3的官网中为我们介绍了一个案例,我们先分析这个案例后再实战自己封装一个useTable的逻辑。

引入官网的鼠标跟踪案例:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const x = ref(0)
const y = ref(0)

function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}

onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

在上述代码中实现了对鼠标位置实时跟踪的功能。我们发现案例中的x、y的状态在鼠标移动时发生变化。不同于封装一个时间格式化的函数,我们只需要传入时间和传出时间,其中的时间是无状态的。因此我们要如何封装这样的公共逻辑呢?

我们将上面的逻辑以一个组合式函数的形式提取到外部文件中:

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

在组件中的使用方式:

<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

我们可以看到,上面封装的函数中向外暴露了我们组件中需要使用的返回值x和y,并且在组件中是可以实现响应式变化的。

上述案例大概让你明白了为什么要封装Hooks函数和如何封装和使用一个Hooks函数。

接下来我们分析一下怎么将前端项目中的Table使用逻辑封装成一个useTable的组合式函数。

封装useBorder Hooks

因为项目中使用了dataV组件,当页面宽高发生变化时组件的宽高总是无法自适应,官网给出了一个解决方案:

实现代码如下:

<BorderBox8 class="borderbox8" :key="key"></BorderBox8>
...
// dataV宽高自适应的key
let key = ref(1);

// 宽高改变框图自适应
function initBorder() {
	window.addEventListener('resize', function () {
		nextTick(() => {
			key.value++;
		});
	});
}
initBorder();

我们在多个页面都使用了dataV的组件,因此我们在多个地方都需要上述代码来实现dataV的宽高自适应。因此就想重用这段代码。在页面发生resize后key值是在发生变化的,因此我们可以用组合式函数来实现复用:

/*
 * @Description: 公用的Datav初始化逻辑,在使用dataV组件时使用
 */
import { ref, onMounted, nextTick } from 'vue';

export function useBorder() {
	const key = ref<number>(1);

	function initBorder() {
		nextTick(() => {
			console.log('resize', key.value);
			key.value++;
		});
	}
	onMounted(() => {
		window.addEventListener('resize', initBorder);
	});
	return { key };
}

在页面中使用:

import { useBorder } from '@/hooks/useBorder';
const { key } = useBorder();

封装useTable Hooks

以下案例用我目前在开发的项目作为示例,采用Typescript进行函数封装。

需要提供的功能:请求表格数据,传递分页信息

useTable中我们要实现请求接口数据,并暴露请求后的数据。因此我们需要向里面传递请求api,通过在不同的地方传入不同的请求api来实现请求不同的数据。

export interface ListResponse<R extends object> {
	code: number;
	data: {
		list: R[];
	};
}
/*
 * @Description: 公用的table逻辑,在使用表格时使用
 */
import { HttpResponse } from '@/utils/request';
import { Paging, ListResponse } from '@/api/types';
import { computed, reactive, toRefs } from 'vue';


interface TableState<R extends object> {
	tableData: R[];
	loading: boolean;
}
interface OtherSearchParams {
	[key: string]: unknown;
}
interface TableBaseMethodsType<R extends object> {
	requestApi: (
		page: number,
		keyword?: string
	) => Promise<HttpResponse<ListResponse<R>>>;
	otherSearchParams?: OtherSearchParams;
}
// table的常见数据请求和分页交互
// 接收:表格数据的范型T, 请求方法以及参数
// 抛出以下:
export default function useTable<R extends object>(
	config: TableBaseMethodsType<R>
) {
	const { otherSearchParams = {}, requestApi } = config;
	const tableState = reactive<TableState<R>>({
		loading: false,
		tableData: []
	});
	// 分页参数
	const pageParams = reactive<Paging>({
		page: 1
	});
	// 分页器配置项
	const pagination = computed(() => {
		return {
			total: tableState.tableData.length,
			curruntPage: pageParams.page
		};
	});
	/**
	 * @description: 请求加载数据
	 * @return {*}
	 */
	const loadList = async () => {
		const page = pageParams.page;
		const params = { ...otherSearchParams };
		// console.log(params, 'params');
		tableState.loading = true;
		try {
			const res = await requestApi(page, params.keyword);
			console.log(res);
			if (res.status === 200) {
				console.log(res.data.data.list, 'data');
				tableState.tableData = res.data.data.list;
				console.log(tableState.tableData, '111');
			}
		} catch (error) {
			console.log(error);
			tableState.tableData = [];
		} finally {
			tableState.loading = false;
		}
	};
	return {
		...toRefs(tableState),
		...toRefs(pageParams),
		pagination,
		loadList
	};
}
h (error) {
console.log(error);
tableState.tableData = [];
} finally {
tableState.loading = false;
}
};
return {
…toRefs(tableState),
…toRefs(pageParams),
pagination,
loadList
};
}

向外暴露请求数据,分页项。基本就实现了我们想要的逻辑了。

​总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 如何使用vue3+uni-app封装音乐播放插件

    如何使用vue3+uni-app封装音乐播放插件

    UniApp是一个基于Vue.js开发的跨平台应用开发框架,它可以使用一套代码同时构建iOS、Android和Web应用,这篇文章主要给大家介绍了关于如何使用vue3+uni-app封装音乐播放插件的相关资料,需要的朋友可以参考下
    2023-11-11
  • Vue FileManagerPlugin 报错问题及解决

    Vue FileManagerPlugin 报错问题及解决

    这篇文章主要介绍了Vue FileManagerPlugin 报错问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • React Diff算法不采用Vue的双端对比原因详解

    React Diff算法不采用Vue的双端对比原因详解

    这篇文章主要介绍了React Diff算法不采用Vue双端对比算法原因详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 详解vue-cli构建项目反向代理配置

    详解vue-cli构建项目反向代理配置

    本篇文章主要介绍了详解vue-cli构建项目反向代理配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • vue任意关系组件通信与跨组件监听状态vue-communication

    vue任意关系组件通信与跨组件监听状态vue-communication

    这篇文章主要介绍了vue任意关系组件通信与跨组件监听状态vue-communication,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • VUE 组件的计算属性详解

    VUE 组件的计算属性详解

    这篇文章主要介绍了VUE组件的计算属性详解,使用计算机属性还是methods取决于你是否需要缓存,当遍历大数组和做大量计算时,应当使用计算机属性,除非你不希望得到缓存,下文来了解具体详情
    2022-06-06
  • vue3声明响应式状态使用(含ref,reactive,toRef(),toRefs()等)

    vue3声明响应式状态使用(含ref,reactive,toRef(),toRefs()等)

    这篇文章主要介绍了vue3声明响应式状态使用(含ref,reactive,toRef(),toRefs()等),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • vue实现分页的三种效果

    vue实现分页的三种效果

    这篇文章主要为大家详细介绍了vue实现分页的三种效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • vue实现用户动态权限登录的代码示例

    vue实现用户动态权限登录的代码示例

    这篇文章主要介绍了vue如何实现用户动态权限登录,文中的代码示例介绍的非常详细,对大家学习vue有一定的帮助,需要的朋友可以参考阅读
    2023-05-05
  • Vue3+Canvas实现简易的贪吃蛇游戏

    Vue3+Canvas实现简易的贪吃蛇游戏

    贪吃蛇作为一个经典的小游戏,是很多人儿时的记忆,当时的掌机、诺基亚手机里面都有它的身影。本文将用Vue3 Canvas来复刻一下这款游戏,感兴趣的可以了解一下
    2022-07-07

最新评论