hooks&&状态管理&&业务管理

前言

最近参与了一个项目,让我印象最深的就是它的 业务逻辑 和 状态管理 ,可以说,第一次见到的时候有些震惊。这个项目是 pnpm 的 workspace 形式,管理多个项目,共享一个 packages 包。

所有的 "js" 都放在这里,如 api、tools和hooks等。

hooks

最开始,我对hooks的解读就是拥有状态、生命周期的特殊函数。最标准的就是在 react 中的 useState ,后面就慢慢地理解成了管理某个状态的钩子,传入一个变量,然后从这个钩子中结构出 变量 和 设置变量。如:

ts 复制代码
const {count,setCount} = useState(0)

基于这种见解,我们就可以封装一些hooks,如设置白天黑夜主题的 useTheme 的hooks等等,没错,我的想法还停留在 hooks 是公共的函数。

后面在vue3中,或者说 pinia 中,有用到了这种这种形式。在进行状态中,store仓库的命名,在习惯上确实是 use------开头。如有个 useInfo 的仓库。

ts 复制代码
const {token , setToken} = useInfo('')

还是上面那句话,我的思想还局限于"公共"的概念,就是说业务逻辑是不用这种方式的。

状态管理

这个项目的状态管理,更准确的说法是状态与逻辑管理,就是借鉴 react 的hooks 和 pinia 进行的自定义管理。

如一个任务页面,获取任务列表。这里涉及到四个文件:

  • 列表的接口: task/index.ts
  • 状态管理的文件:useTask/useTaskStore.ts
  • 处理逻辑的文件:useTask/index.ts
  • 页面文件:index.vue

列表接口

每一个接口都是一个命名空间,一个文件。

ts 复制代码
export namespace ReqTaskList {
	export const config: REQ_CONFIG_ITEM = {
		url: "task/list",
		host: HOST_NAME.activity,
		method: HTTP_METHOD.get,
	};

	export interface RequestData {
		// TODO: 接口信息待补充
	}

	export interface itemVo {
		current: string;
		dyAdAwardLeft: number;
		enumType: string;
		icon: string;
		link: string;
		name: string;
		rewardDesc: string;
		status: number;
		target: string;
		taskId: number;
	}
	export interface ResponseData {
		dailyTasks: itemVo[];
		growthTasks: itemVo[];
		weeklyTasks: itemVo[];
	}

	export async function request(data?: RequestData) {
		return await commonRequest<RequestData, ResponseData>(config, data);
	}
}

状态管理的文件

这里是定义了全局的任务数据仓库,使用 工厂模式 创建了一个可销毁的单例模式。

在这个文件管理页面所需要的响应式数据。

ts 复制代码
import { ref } from "vue";
import { ReqTaskList } from "@lv/request";

interface ItemVo extends ReqTaskList.itemVo {
	img?: string;
	btnText?: string;
}
class TaskStore {
	constructor() {}
	dailyTasks = ref<ItemVo[]>([]);
	growthTasks = ref<ItemVo[]>([]);
	weeklyTasks = ref<ItemVo[]>([]);
}

let _taskStore: TaskStore | null = null;

function initTaskStore() {
	_taskStore = new TaskStore();
}

function unInstallTaskStore() {
	_taskStore = null;
}

function useTaskStore(): TaskStore {
	if (!_taskStore) initTaskStore();
	return _taskStore as TaskStore;
}

export { initTaskStore, unInstallTaskStore, useTaskStore };
export type { ItemVo };

处理逻辑的文件

所有的业务逻辑都在这个文件里进行,包括接口请求、数据处理等逻辑。

ts 复制代码
import { onUnmounted, onMounted } from "vue";
import { ReqTaskList, ReqTaskTurntableActivity } from "@lv/request";
import { unInstallTaskStore, useTaskStore, ItemVo } from "./useTaskStore";
import { useUser } from "../useUser";
import { formatImg } from "@lv/tool";
export function useTask() {
	const { userId } = useUser();
	const taskStore = useTaskStore();
	const { dailyTasks, growthTasks, weeklyTasks } = taskStore; // 导出响应式数据

	const formatList = (list: ItemVo[]) => {
		return list.map((item) => {
			const obj = JSON.parse(JSON.stringify(item));
			obj.img = formatImg(item.icon);
			switch (parseInt(item.status.toString())) {
				case 1:
					obj.btnText = "领取";
					break;
				case 0:
					obj.btnText = "去完成";
					break;
				case 2:
					obj.btnText = "已领取";
					break;
			}
			return obj;
		});
	};
        
  // 获取列表数据
	const getTaskList = async () => {
		try {
			const res = await ReqTaskList.request();
			dailyTasks.value = formatList(res.data.dailyTasks);
			growthTasks.value = formatList(res.data.growthTasks);
			weeklyTasks.value = formatList(res.data.weeklyTasks);
		} catch (error) {}
	};

	const getTurntableActivity = async (
		params: ReqTaskTurntableActivity.RequestData
	) => {
		if (!userId.value) return;
		try {
			const res = await ReqTaskTurntableActivity.request(params);
			return res;
		} catch (error) {}
	};

// 初始化
	onMounted(() => {
		getTaskList();
	});
	onUnmounted(() => {
		unInstallTaskStore();
	});

	return {
		taskStore,
		getTaskList,
		getTurntableActivity,
	};
}

最后在页面上引入数据并使用就可以了。

vue 复制代码
<script>
import { useTask } from "@lv/hooks";
const { taskStore, getTaskList } = useTask();
const {
	dailyTasks: dailyTasksList,
	growthTasks: growthTasksList,
	weeklyTasks: weeklyTasksList,
} = taskStore;
</script>

看法

这种处理方法,我说不上来好还是不好,或者说合不合适。现在只是一两个变量和方法,在处理的时候还是比较简单,但仍然是需要在 逻辑管理 和 处理逻辑 这两个文件之间跳转,如果变量和方法多一些,那处理起来我会觉得更加费劲。大家如何看呢?

相关推荐
aricvvang2 小时前
一行 Promise.all 争议:数据库查询并行真的没用?我和同事吵赢了!!!
javascript·后端·node.js
三掌柜6662 小时前
2025三掌柜赠书活动第三十五期 AI辅助React Web应用开发实践:基于React 19和GitHub Copilot
前端·人工智能·react.js
YH丶浩2 小时前
vue自定义数字滚动插件
开发语言·前端·javascript·vue
阿民_armin2 小时前
Canvas 冷暖色分析工具
前端·javascript·vue.js
小岛前端2 小时前
大小仅 1KB!超级好用!计算无敌!
前端·javascript·开源
没有鸡汤吃不下饭2 小时前
Git将某个分支合并到开发(dev)、测试(test)后突然想撤销该分支的功能,怎么处理?
前端·git·github
文心快码BaiduComate3 小时前
Comate分饰多角:全栈开发一个Python学习网站
前端·后端·python
90后的晨仔3 小时前
Vue 插槽(Slots)全面解析与实战指南
前端·vue.js
我是日安3 小时前
从零到一打造 Vue3 响应式系统 Day 20 - Reactive:reactive 极端案例
前端·vue.js