# mobile **Repository Path**: ZY-LMP/mobile ## Basic Information - **Project Name**: mobile - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-07 - **Last Updated**: 2025-08-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 移动端键盘处理工具 这是一个Vue3+TypeScript的工具,用于解决移动端(iOS Safari和Android Edge)浏览器中键盘相关的问题: - 当输入框失去焦点时自动收起键盘 - 点击发送按钮时强制收起键盘 - 处理安卓"前往"键和iOS Safari"换行"键点击时键盘不收起的问题 - 彻底解决Edge浏览器键盘收起时的闪动问题 - 页面滚动时自动收起键盘(增强版滚动检测) - 支持处理多个输入框的键盘行为 ## 功能特点 - 兼容iOS Safari和Android Edge浏览器 - 处理移动设备键盘上的"前往"/"换行"键 - 彻底解决Edge浏览器键盘收起闪动问题 - 增强的滚动检测,确保键盘在滚动时可靠收起 - 支持处理多个输入框 - 支持表单提交事件处理 - 自动检测设备类型并应用对应处理 - 采用Vue3组合式API - 支持TypeScript类型安全 - 灵活的配置选项 - 简单易用的接口 ## 使用方法 ### 基本用法 ```typescript import { useKeyboard } from '@/utils/keyboard' import { ref } from 'vue' // 输入框和发送按钮的引用 const inputRef = ref(null) const sendBtnRef = ref(null) // 使用键盘处理工具 const { hideKeyboard, isIOS, isAndroid, isEdge, isKeyboardOpen } = useKeyboard({ inputRef, sendBtnRef, autoRegister: true, // 自动注册事件 hideOnScroll: true // 启用滚动时收起键盘 }) // 可以在任何地方手动关闭键盘 const handleSomeAction = () => { // 工具会自动处理Edge浏览器闪动问题 hideKeyboard() } // 检查键盘是否处于打开状态 const checkKeyboardStatus = () => { console.log('键盘是否打开:', isKeyboardOpen()) } ``` ### 处理多个输入框 当页面中有多个输入框需要处理时,可以使用`inputRefs`参数: ```typescript import { useKeyboard } from '@/utils/keyboard' import { ref } from 'vue' // 定义多个输入框引用 const input1Ref = ref(null) const input2Ref = ref(null) const input3Ref = ref(null) // 使用键盘处理工具,传入输入框数组 const { hideKeyboard } = useKeyboard({ // 传入多个输入框引用数组 inputRefs: [input1Ref, input2Ref, input3Ref], autoRegister: true, hideOnScroll: true }) ``` 在模板中使用: ```html
``` ### 监听键盘状态 使用Vue的watch监听键盘状态变化: ```typescript import { watch } from 'vue' // 使用键盘处理工具 const { isKeyboardOpen } = useKeyboard({ // ...options }) // 监听键盘状态变化 watch(isKeyboardOpen, (isOpen) => { console.log('键盘状态:', isOpen ? '打开' : '关闭') }) ``` ### 处理键盘回车键 在模板中添加回车键处理: ```html
``` ### 禁用滚动收起键盘功能 如果你不想在滚动时自动收起键盘: ```typescript const { hideKeyboard } = useKeyboard({ inputRef, sendBtnRef, autoRegister: true, hideOnScroll: false // 禁用滚动时收起键盘 }) ``` ### 防止Edge浏览器闪动 为Edge浏览器添加额外防护措施: ```typescript import { onMounted } from 'vue' onMounted(() => { // 如果是Edge浏览器,添加特殊处理 if (isEdge) { // 添加防止页面缩放的meta标签 const viewportMeta = document.querySelector('meta[name="viewport"]') if (viewportMeta) { viewportMeta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no') } else { const meta = document.createElement('meta') meta.name = 'viewport' meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' document.head.appendChild(meta) } // 阻止缩放相关事件 document.addEventListener('touchmove', (e) => { if (e.touches.length > 1) { e.preventDefault() } }, { passive: false }) } }) ``` ### 手动注册事件 如果不想自动注册事件,可以: ```typescript const { hideKeyboard, registerEvents, isEdge } = useKeyboard({ inputRef, sendBtnRef, autoRegister: false }) // 在需要的时候手动注册事件 onMounted(() => { registerEvents() }) ``` ### 直接使用DOM元素 如果你需要在非组件环境中使用: ```typescript import { useKeyboardHandler, useMultipleKeyboardHandlers, closeKeyboard, isIOS, isAndroid, isEdgeBrowser, registerScrollToHideKeyboard } from '@/utils/keyboard' // 获取DOM元素 const inputElements = document.querySelectorAll('input') const sendButton = document.querySelector('button') // 注册事件 - 处理单个输入框 if (inputElements[0]) { useKeyboardHandler(inputElements[0], sendButton) } // 或者注册事件 - 处理多个输入框 if (inputElements.length > 0) { useMultipleKeyboardHandlers( Array.from(inputElements) as HTMLInputElement[], sendButton ) } // 注册滚动时收起键盘 const cleanup = registerScrollToHideKeyboard() // 不再需要时清理事件 // cleanup() // 可以检查设备类型 if (isIOS()) { // iOS专用处理 } else if (isAndroid()) { // Android专用处理 } // Edge浏览器专用处理 if (isEdgeBrowser()) { // 设置视口锁定,防止闪动 document.querySelector('meta[name="viewport"]')?.setAttribute( 'content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' ) } // 在任何地方手动关闭键盘 function someHandler() { // 第二个参数为true可以启用平滑关闭模式 closeKeyboard(isEdgeBrowser()) } ``` ## 增强的滚动检测原理 增强的滚动检测功能通过以下方式实现,确保键盘在滚动时可靠收起: 1. **多层次事件监听**: - 同时监听window和document的滚动事件 - 使用事件捕获阶段(capture: true)确保先于其他处理器执行 - 处理触摸事件和滚动事件的配合 2. **活跃输入框跟踪**: - 记录最后一个获得焦点的输入元素 - 即使当前没有元素处于焦点状态,也能找到需要处理的输入框 3. **状态检测定时器**: - 使用定期检测机制,监控键盘状态 - 自动检测并处理意外的状态不一致情况 4. **窗口大小变化检测**: - 监听resize事件,它通常在键盘弹出/收起时触发 - 提供额外的检测机会,提高可靠性 5. **文档状态检查**: - 检查document.activeElement来确认当前焦点状态 - 在滚动时主动让活跃输入元素失去焦点 ## 滚动收起键盘原理 滚动收起键盘功能通过以下方式实现: 1. **滚动事件监听**:监听窗口的滚动事件,当检测到滚动时检查键盘状态 2. **触摸事件处理**:监听触摸开始和移动事件,计算垂直移动距离 3. **键盘状态跟踪**:通过输入框的focus/blur事件跟踪键盘打开/关闭状态 4. **自动关闭**:当滚动发生且键盘处于打开状态时,自动使当前输入元素失去焦点并关闭键盘 ## 多输入框处理原理 多输入框处理功能通过以下方式实现: 1. **输入框数组管理**:接收多个输入框的ref引用数组 2. **批量事件注册**:为每个有效的输入框元素注册必要的事件处理函数 3. **统一键盘状态**:所有输入框共享同一个键盘状态管理 4. **统一滚动处理**:滚动时会检查当前激活的输入框,并使其失去焦点 ## Edge浏览器闪动问题彻底解决方案 对于Edge浏览器键盘收起时的闪动问题,本工具采取了以下解决方案: 1. **滚动位置锁定**:保存和恢复滚动位置,防止页面跳动 2. **视口控制**:临时锁定页面滚动,防止键盘收起时的视觉闪动 3. **延迟处理**:使用更科学的延迟策略,确保Edge浏览器有足够时间处理UI变化 4. **事件优化**:优化事件处理顺序,确保平滑过渡 5. **视口锁定**:通过meta标签禁用缩放功能,减少布局重绘 6. **样式优化**:添加特殊样式防止输入元素引起的布局变化 ## 工作原理 该工具通过以下几种方式处理移动设备键盘: 1. **基本键盘收起**:创建临时不可见输入元素,并控制其焦点状态来强制关闭移动设备的虚拟键盘 2. **失焦处理**:监听输入框的blur事件,确保失去焦点时关闭键盘 3. **按钮点击处理**:监听发送按钮点击事件,在点击时关闭键盘 4. **键盘按键处理**: - 监听keyup/keydown事件处理键盘上的回车键(安卓"前往"和iOS"换行"键) - 对表单提交事件进行处理,确保提交时键盘收起 5. **增强的滚动处理**: - 多层次事件监听确保可靠捕获所有滚动行为 - 记录最后激活的输入元素,确保始终能找到需要处理的输入框 - 定时状态检测,解决可能的状态不一致问题 6. **多输入框处理**: - 支持同时处理多个输入框 - 为每个输入框注册必要的事件 7. **设备检测**:提供isIOS()、isAndroid()和isEdgeBrowser()方法用于检测设备类型和浏览器类型,便于做针对性处理 8. **Edge浏览器优化**: - 针对Edge浏览器的闪动问题提供专门的优化处理 - 使用滚动位置锁定和恢复机制 - 临时禁用页面滚动防止视觉跳动