vibrate 可用需同时满足:typeof navigator.vibrate === 'function' 且在用户手势事件(如 click)中调用;iOS 不支持,后台或非可见页静默失效;推荐 navigator.vibrate(150),避免数组兼容问题。
不能直接用 navigator.vibrate() 就生效 —— 它必须在用户真实手势中调用,且 iOS 全面不支持,否则静默失败。
只写 'vibrate' in navigator 会误判:iOS Safari 返回 true,但实际调用无效。必须叠加类型检查:
typeof navigator.vibrate === 'function' 是唯一可靠判断方式click、touchend 等用户手势事件触发,setTimeout 或 Promise 回调里调用会直接丢弃document.visibilityState !== 'visible')时也会静默失效单数字最稳妥,数组易踩兼容性坑:
navigator.vibrate(150):Android 主流浏览器响应快,用户感知清晰[100, 50, 100] 这类短间隔组合 —— 部分低端 Android 设备无法解析停顿,合并成一次长震0 或 [] 可清空当前震动队列,但通常没必要主动调用震动不是独立动作,必须绑定到可感知的交互闭环里:
button、switch、form submit 等明确由用户触发的操作末尾调用,比如 onclick 处理函数最后scroll、input、hover 或自动轮播中触发 —— 违反手势前提,必失效matchMedia('(prefers-reduced-motion: reduce)') 匹配时跳过震动;iOS 或检测失败时改用 CSS 抖动动画或轻量音效真正容易被忽略的是「用户手势上下文」这个硬性前提 —— 它不是可选优化,而是浏览器强制策略。哪怕所有检测都通过,只要调用栈里没有真实的 click/touchend 事件路径,震动就永远不会发生。