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>

看法

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

相关推荐
Dream-Y.ocean1 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Csvn2 小时前
性能监控
前端
Highcharts.js2 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn2 小时前
构建工具
前端
FRing033 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷3 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen5 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒5 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫6 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus6 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude