Vue 3 蓝牙管理通过分层组合式函数抽象:useBluetooth 封装连接生命周期,useBluetoothService 抽象服务交互,useBluetoothQueue 解决并发冲突,useHeartRateMonitor 组合业务逻辑。

Vue 3 实现蓝牙设备管理的逻辑抽象,核心是把“连接、扫描、读写特征值、断开、错误重试”等重复性操作封装成可复用、可组合、可测试的组合式函数(Composables),而不是散落在各个页面中硬编码蓝牙 API 调用。
用 useBluetooth 管理基础连接生命周期
这是最底层的逻辑抽象,负责统一处理 Web Bluetooth API 的调用、状态维护和错误兜底:
- 封装
navigator.bluetooth.requestDevice和device.gatt.connect(),返回响应式连接状态(isConnected、device、server) - 自动监听
gattserverdisconnected事件,在断连时触发清理并重置状态 - 暴露
connect()、disconnect()方法,支持传入过滤条件(如filters: [{ services: ['battery_service'] }]) - 内部使用
onUnmounted自动断连,避免内存泄漏
用 useBluetoothService 封装特定服务交互
在已连接基础上,进一步按 GATT 服务抽象——比如电池服务、心率服务、自定义传感器服务:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 接收
server和serviceUUID,自动获取 service、characteristic,并缓存引用 - 提供
readValue()、writeValue()、startNotifications()等语义化方法 - 对通知(Notifications)做防抖处理:同一 characteristic 多次订阅只生效一次;取消时自动移除监听器
- 返回的 value 是
ref,支持模板直接绑定,例如{{ batteryLevel }}
用 useBluetoothQueue 解耦多指令并发冲突
针对你提到的“A 页面定时发指令、B 页面也要发、怕冲突”的典型场景,必须引入指令队列层:
立即学习“前端免费学习笔记(深入)”;
- 全局单例队列(推荐用
const queue = reactive({ list: [], executing: false })),所有页面调用addCommand({ type: 'write', service: '0x180f', char: '0x2a19', value: new Uint8Array([1]) }) - 队列自动串行执行,确保任意时刻只有一个蓝牙操作在进行;失败指令可配置重试次数与间隔
- A 页面的定时器不直接调蓝牙,而是每秒调
addCommand(...);离开页面时可暂停本页指令入队(queue.enabled = false),但不影响队列中已有任务 - B 页面发送高优指令时可加
priority: true,插到队首立即执行
按业务组合:比如 useHeartRateMonitor
在基础层之上,面向具体功能组装高阶逻辑:
- 内部组合
useBluetooth+useBluetoothService('heart_rate') - 自动解析心率测量 characteristic 的原始 buffer(含标志位、单位、能量扩展等)
- 内置采样节流(如 1Hz 限频)、离线缓存、心跳异常告警逻辑
- 对外只暴露
heartRate、isMeasuring、start()、stop(),UI 层完全不用关心蓝牙细节

















