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>

看法

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

相关推荐
Jmyd01238 小时前
Web端3D营销展厅技术实现路径:从素材上云到线索回流的数据链路
前端·3d·性能优化·三维数字化
半个落月8 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
砚凝霜8 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
半个落月8 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
u01110267510 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus10 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
派小心.11 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
hhb_61811 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
Java后端的Ai之路11 小时前
08_React组件API
前端·react.js·前端框架
小马不起床11 小时前
零基础玩转 FastAPI_09:前端基础工程构建
前端·状态模式·fastapi