YAOTU INSIGHTS

Hyperapp Subscriptions完全讲解:键盘、鼠标、时间事件订阅与5个生命周期管理技巧

Hyperapp Subscriptions完全讲解:键盘、鼠标、时间事件订阅与5个生命周期管理技巧
Hyperapp Subscriptions完全讲解键盘、鼠标、时间事件订阅与5个生命周期管理技巧【免费下载链接】hyperapp1kB-ish JavaScript framework for building hypertext applications项目地址: https://gitcode.com/gh_mirrors/hy/hyperappHyperappindex.js是一个仅约 1kB 的 JavaScript 超轻量框架而Subscriptions订阅正是它响应外部事件的核心机制。通过订阅你可以轻松监听键盘按键、鼠标移动、定时器触发等应用外部发生的事情并让事件自动驱动状态更新。本文面向新手用最少代码讲清 Hyperapp 订阅的原理、官方事件包用法和 5 个生命周期管理技巧。什么是 Hyperapp 订阅A subscription function represents a dependency your app has on some external process. 订阅函数代表你的应用对某个外部进程的一项依赖简单记法Effects副作用应用影响外部世界如发请求、聚焦元素Subscriptions订阅应用响应外部世界如用户按下键盘、时钟滴答订阅帮你自动处理添加/移除事件监听、关闭连接等资源管理工作你只需声明我要监听什么、发生时要执行哪个 action。官方建议订阅函数命名采用on前缀的驼峰形式如onEvery、onKeyDown见 docs/architecture/subscriptions.md。开启订阅的 3 个步骤第 1 步在app()定义中提供subscriptions:属性它是一个接收 state、返回订阅数组的函数import { every } from hyperapp/time app({ init: { delay: 1000 }, subscriptions: (state) [ // 每隔 state.delay 毫秒 dispatch 一次 RequestResource every(state.delay, RequestResource), ], })第 2 步订阅数组中的每一项是一个订阅[subscriber, payload?]二元组表示谁监听 监听到后派发什么 action。第 3 步每当状态变化Hyperapp 都会重新调用这个函数对比新旧结果自动启动或停止订阅——你完全不需要手写addEventListener/removeEventListener。省略subscriptions:则等价于subscriptions: (state) []即无订阅见 docs/api/app.md#subscriptions。内置订阅包键盘、鼠标与时间事件Hyperapp 官方提供了两个最常用的订阅包见 README.md 的 Packages 表格按需npm install即可。hyperapp/events键盘与鼠标事件订阅hyperapp/events导出了一批开箱即用的订阅函数源码见 packages/events/index.js#L38-L45订阅函数对应事件典型用途onKeyDown/onKeyUp键盘按下/抬起快捷键、方向键移动选择onMouseMove/onMouseDown/onMouseUp鼠标移动/按下/抬起拖拽、画板、游戏onClick点击全局点击行为onFocus/onBlur聚焦/失焦表单联动官方教程里有一个经典例子用方向键在列表中移动选中项。思路是先写一个监听 keydown、按键名匹配后派发对应 action的订阅再用布尔逻辑控制它是否激活完整代码见 docs/tutorial.md#L604-L689subscriptions: (state) [ state.selected ! null state.selected 0 onKeyDown(ArrowUp, SelectUp), // 第一项时禁用上移 state.selected ! null state.selected state.ids.length - 1 onKeyDown(ArrowDown, SelectDown), // 最后一项时禁用下移 ] 小技巧布尔值前缀就是订阅的开关——条件为假时该位返回falseHyperapp 会自动停止并清理该订阅。hyperapp/time时间事件订阅hyperapp/time提供三个函数源码见 packages/time/index.js#L22-L33every(delay, action)定时循环每delay毫秒派发一次 action附带当前时间戳适合时钟、轮询delay(delay, action)一次性延时派发适合2 秒后弹出提示now(action)立即派发一次当前时间戳适合倒计时基准比如做一个每秒刷新的小时钟import { every, now } from hyperapp/time app({ init: { time: Date.now() }, view: ({ time }) h(p, {}, text(new Date(time).toLocaleTimeString())), subscriptions: () [ now(SetTime), // 启动时立即取一次时间 every(1000, SetTime) // 之后每秒刷新 ], })订阅生命周期Hyperapp 如何管理启停每次状态变化时Hyperapp 都会逐位比较订阅数组之前是否激活与当前是否激活按以下规则处理官方表格见 docs/architecture/subscriptions.md#L58-L67之前状态当前状态Hyperapp 的行为未激活未激活什么都不做未激活激活启动订阅执行 subscriber激活未激活停止订阅并执行清理cleanup激活激活保持运行不受打扰注意要重启一个订阅比如换个监听目标必须先让它失活再在下一次状态变化时重新激活直接换参数并不会重置它。5 个订阅生命周期管理技巧 ️技巧 1订阅数组必须定长 位置固定Hyperapp 靠数组位置追踪订阅所以不要用动态增删的数组也不要把订阅函数内联写在subscriptions:里——每次状态变化都会生成新引用导致订阅反复重置见 docs/architecture/subscriptions.md#L54。正确做法是把订阅工厂函数定义在外部数组里只调用它。技巧 2用布尔值控制订阅的启停state.条件 订阅(...)是最常用的开关模式。配合||还能实现互斥订阅例如state.paused ? pauseSub : resumeSub让不同界面状态各用其需的监听。技巧 3重启 先关再开想让同一个位置的订阅换参数重跑先让布尔条件为假关闭并清理等下一次状态变化再置为真重新打开。这是框架规定的重启姿势。技巧 4subscriber 必须返回清理函数自定义订阅时subscriber 的签名是(dispatch, payload) CleanupFn函数体负责开始监听返回值负责停止监听见 docs/architecture/subscriptions.md#subscribers。忘记返回清理函数 事件监听泄漏。const listenToEvent (dispatch, props) { const listener (e) dispatch(props.action, e.detail) addEventListener(props.type, listener) return () removeEventListener(props.type, listener) // 别忘了它 }技巧 5解构 props 的隐藏陷阱如果清理函数还需要向应用回报消息dispatch action请整体引用props而不是解构{ action, type }。解构会产生局部副本闭包捕获的是创建时的旧 action 引用而非清理执行时最新的那个详解见 docs/architecture/subscriptions.md#L155-L240。总结订阅是 Hyperapp 响应外部世界的声明式通道app()的subscriptions:属性 [subscriber, payload]二元组官方包hyperapp/eventspackages/events/覆盖键盘/鼠标/焦点事件hyperapp/timepackages/time/覆盖定时器场景生命周期由 Hyperapp 自动管理状态驱动启停记住定长数组、布尔开关、先关再开、必返清理、避免解构五要点更多资料可查阅 docs/reference.md 术语表和 docs/architecture/subscriptions.md 完整文档。【免费下载链接】hyperapp1kB-ish JavaScript framework for building hypertext applications项目地址: https://gitcode.com/gh_mirrors/hy/hyperapp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考