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>

看法

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

相关推荐
JNU freshman9 分钟前
vue 之 import 的语法
前端·javascript·vue.js
剑亦未配妥10 分钟前
Vue 2 响应式系统常见问题与解决方案(包含_demo以下划线开头命名的变量导致响应式丢失问题)
前端·javascript·vue.js
爱吃的强哥13 分钟前
Vue2 封装二维码弹窗组件
javascript·vue.js
凉柚ˇ13 分钟前
Vue图片压缩方案
前端·javascript·vue.js
慧一居士13 分钟前
vue 中 directive 作用,使用场景和使用示例
前端
慧一居士15 分钟前
vue 中 file-saver 功能介绍,使用场景,使用示例
前端
ByteCraze28 分钟前
秋招被问到的常见问题
开发语言·javascript·原型模式
优弧30 分钟前
Vue 和 React 框架对比分析:优缺点与使用场景
vue.js
渣哥1 小时前
从代理到切面:Spring AOP 的本质与应用场景解析
javascript·后端·面试
文心快码BaiduComate1 小时前
文心快码3.5S实测插件开发,Architect模式令人惊艳
前端·后端·架构