当前位置: 首页 > news >正文

vue3中封装hooks

有这样的一个封装

// import { ref } from 'vue';// /**
//  * boolean组合式函数
//  * @param initValue 初始值
//  */
// export default function useBoolean(initValue = false) {
// 	const bool = ref(initValue);// 	function setBool(value: boolean) {
// 		bool.value = value;
// 	}
// 	function setTrue() {
// 		setBool(true);
// 	}
// 	function setFalse() {
// 		setBool(false);
// 	}
// 	function toggle() {
// 		setBool(!bool.value);
// 	}// 	return {
// 		bool,
// 		setBool,
// 		setTrue,
// 		setFalse,
// 		toggle
// 	};
// }import useBoolean from './use-boolean';export default function useLoading(initValue = false) {const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);return {loading,startLoading,endLoading};
}// const { loading, startLoading, endLoading } = useLoading();

这是一个使用 Vue 3 组合式 API(Composition API) 编写的自定义 Hook(组合式函数)结构,采用了 函数封装与复用 的设计模式。整体结构清晰、可复用性强,体现了现代前端开发中“逻辑抽象”的思想。

我们来逐步解析这个结构:


🌐 整体结构概览

import useBoolean from './use-boolean';export default function useLoading(initValue = false) {const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);return {loading,startLoading,endLoading};
}

🔍 分析:useLoading 的作用

useLoading 是一个自定义组合式函数(Custom Composition Function),它的目的是:

封装“加载状态”相关的逻辑,提供简洁易用的 API 来控制 loading 状态。

它本身不直接操作 DOM 或响应数据,而是复用另一个更通用的 useBoolean 函数来管理布尔值状态。


🔗 依赖:useBoolean 函数(被注释掉的部分)

虽然被注释了,但它是核心基础。我们先还原它的功能:

import { ref } from 'vue';export default function useBoolean(initValue = false) {const bool = ref(initValue);function setBool(value: boolean) {bool.value = value;}function setTrue() {setBool(true);}function setFalse() {setBool(false);}function toggle() {setBool(!bool.value);}return {bool,setBool,setTrue,setFalse,toggle};
}

这个函数是一个通用的布尔状态管理器,返回:

  • bool: 响应式布尔值(ref<boolean>
  • setBool(value): 设置为任意布尔值
  • setTrue(): 设为 true
  • setFalse(): 设为 false
  • toggle(): 切换状态

✨ useLoading 如何利用 useBoolean

const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);

这里使用了 ES6 解构赋值 + 别名(alias) 技术:

原名(来自 useBoolean别名(在 useLoading 中使用)含义
boolloading表示当前是否处于加载状态
setTruestartLoading开始加载(设为 true)
setFalseendLoading结束加载(设为 false)

💡 这是一种“语义化封装”:将通用的布尔操作包装成具有业务含义的名称。

1.为什么不用普通变量?

我们来看一个反例

// ❌ 错误示例:不用 ref
let bool = false;function setTrue() {bool = true; // 普通赋值
}

问题来了:

  • 这个 bool 是一个普通的 JavaScript 变量。
  • 当你在 Vue 组件中使用它时,Vue 根本不知道这个变量发生了变化
  • 所以即使你调用了 setTrue(),页面上的视图不会更新

👉 Vue 的响应式系统只追踪通过 refreactive 等方式定义的响应式数据。

2. ref 如何实现响应式?

当你用 ref(initValue) 创建变量时,Vue 做了这些事:

  • 把这个值包装成一个带有 .value 的对象。
  • 在背后监听 .value 的读取和写入操作(通过 get / set 代理)。
  • 一旦 .value 被修改,Vue 就知道“这个数据变了”,然后重新渲染依赖它的模板。
const bool = ref(false);// 在模板中使用:
// <div v-if="bool">正在加载...</div>// 调用 setTrue()
setTrue(); // → bool.value = true → Vue 检测到变化 → 更新视图

3. 在 useBoolean 中的作用

export default function useBoolean(initValue = false) {const bool = ref(initValue); // ✅ 响应式布尔值function setBool(value: boolean) {bool.value = value; // 修改响应式数据}return {bool,        // 返回响应式引用,供外部使用setBool,setTrue,setFalse,toggle};
}

这样,任何使用这个 Hook 的组件都可以:

  • 读取 bool.value(在 JS 中)或 bool(在模板中自动解包)
  • 调用 setTrue() 等方法改变状态
  • 页面自动更新

4. 模板中使用 ref 时的“自动解包”

有趣的是,在模板中使用 ref 时,Vue 会自动帮你解开 .value

<script setup>
import useBoolean from './use-boolean';
const { bool, toggle } = useBoolean();
</script><template><!-- 不需要写 bool.value,Vue 自动解包 --><p>{{ bool ? '开' : '关' }}</p><button @click="toggle">切换</button>
</template>

但在 JS/TS 中操作时,必须手动加 .value

bool.value = true; // 必须 .value

📦 最终返回的 API

return {loading,startLoading,endLoading
};

调用者可以这样使用:

const { loading, startLoading, endLoading } = useLoading(false);// 开始请求
async function fetchData() {startLoading(); // 显示加载中...try {const data = await api.getData();} finally {endLoading(); // 隐藏加载状态}
}

🏗️ 架构设计思想总结

特性说明
✅ 逻辑复用useLoading 复用了 useBoolean,避免重复写 ref 和 setXXX
✅ 语义清晰将 setTrue 改名为 startLoading,让调用者更容易理解用途
✅ 职责分离useBoolean 负责基础逻辑,useLoading 负责业务语义
✅ 类型友好(TypeScript)返回的对象结构明确,便于类型推导
✅ 可扩展性可以继续扩展如 toggleLoading 或添加延迟、防抖等特性

🔄 类比理解(类比 React)

如果你熟悉 React,这类似于:

// 自定义 Hook
function useBoolean(init) { ... }
function useLoading(init) { return useBoolean(init); }

只不过 Vue 的 ref + reactive 提供了更细粒度的响应式系统。


✅ 使用建议

你可以进一步增强 useLoading

export default function useLoading(initValue = false) {const { bool: loading, setTrue: startLoading, setFalse: endLoading, toggle } = useBoolean(initValue);// 可选:带自动结束的 loadingfunction withLoading(promise) {startLoading();return Promise.resolve(promise).finally(endLoading);}return {loading,startLoading,endLoading,toggle, // 也可以暴露 togglewithLoading // 高阶用法:自动管理异步加载};
}

然后:

withLoading(fetchData()); // 自动开始和结束 loading
http://www.dtcms.com/a/338924.html

相关文章:

  • uniapp 应用未安装:软件包与现有软件包存在冲突
  • GEO 优化专家孟庆涛:技术破壁者重构 AI 时代搜索逻辑
  • Flask 路由与视图函数绑定机制
  • 正式签约 | OpenLoong 项目正式捐赠至开放原子开源基金会,成为全国首个具身智能方向孵化项目!
  • 【图像算法 - 18】慧眼辨良莠:基于深度学习与OpenCV的麦田杂草智能识别检测系统(附完整代码)
  • 哈希:两数之和
  • Mac(七)右键新建文件的救世主 iRightMouse
  • python将epub文件转pdf
  • UniApp 实现pdf上传和预览
  • 大模型级部署:从本地轻量化到云原生方案
  • 基于单片机智能密码锁/密码箱/门锁/门禁系统
  • Python爬虫实战:研究ICP-Checker,构建ICP 备案信息自动查询系统
  • PiscCode迅速集成YOLO-Pose 实现姿态关键点轨迹跟踪应用
  • 从繁琐到优雅:Java Lambda 表达式全解析与实战指南
  • 第1章 React组件开发基础
  • JxBrowser 8.10.0 版本发布啦!
  • iOS App 混淆工具实战,教育培训类 App 的安全保护方案
  • CTFshow系列——命令执行web34-37
  • RK3128增加usb调试模式,开放adb和root权限
  • leetcode 有效的括号
  • 西游记23:三藏不忘本,四圣试禅心;八戒挑行李;分工明确;
  • Java试题-选择题(11)
  • 从闲置到珍宝:旧物回收小程序系统重塑物品价值
  • dockerfile文件中crlf与lf换行符问题
  • 记录Webapi Excel 导出
  • 电影购票+票房预测系统 - 后端项目介绍(附源码)
  • Android Studio常用知识总结
  • HP Pavilion G6 笔记本使用ventoy启动安装Ubuntu 22.04 桌面版
  • Redission是什么
  • 低延迟、跨平台与可控性:直播SDK的模块化价值解析