import { create } from 'zustand' import Taro from '@tarojs/taro' interface KeyboardState { keyboardHeight: number isKeyboardVisible: boolean listeners: Set<(height: number, visible: boolean) => void> isInitialized: boolean } interface KeyboardActions { setKeyboardHeight: (height: number) => void setKeyboardVisible: (visible: boolean) => void addListener: (listener: (height: number, visible: boolean) => void) => () => void initializeKeyboardListener: () => void cleanup: () => void } type KeyboardStore = KeyboardState & KeyboardActions export const useKeyboardStore = create((set, get) => ({ keyboardHeight: 0, isKeyboardVisible: false, listeners: new Set(), isInitialized: false, setKeyboardHeight: (height: number) => { // 直接更新状态,不触发监听器(监听器由 initializeKeyboardListener 统一处理) set({ keyboardHeight: height }) }, setKeyboardVisible: (visible: boolean) => { // 直接更新状态,不触发监听器(监听器由 initializeKeyboardListener 统一处理) set({ isKeyboardVisible: visible }) }, addListener: (listener: (height: number, visible: boolean) => void) => { const { listeners } = get() listeners.add(listener) // 返回取消监听的函数 return () => { listeners.delete(listener) } }, initializeKeyboardListener: () => { const { isInitialized } = get() if (isInitialized) return console.log('初始化全局键盘监听器') // 使用防抖优化,避免频繁触发 let lastHeight = 0 let lastTime = 0 let pendingUpdate: { height: number; visible: boolean } | null = null let rafId: number | null = null const debounceDelay = 50 // 增加到50ms,减少更新频率 const applyUpdate = () => { if (!pendingUpdate) return const { height, visible } = pendingUpdate const store = get() // 批量更新,减少状态更新次数 if (visible) { set({ isKeyboardVisible: true, keyboardHeight: height }) // 异步通知监听器 requestAnimationFrame(() => { const { listeners } = get() listeners.forEach(listener => { try { listener(height, true) } catch (error) { console.error('键盘监听器执行错误:', error) } }) }) } else { set({ isKeyboardVisible: false, keyboardHeight: 0 }) // 异步通知监听器 requestAnimationFrame(() => { const { listeners } = get() listeners.forEach(listener => { try { listener(0, false) } catch (error) { console.error('键盘监听器执行错误:', error) } }) }) } pendingUpdate = null rafId = null } Taro.onKeyboardHeightChange?.((res: any) => { const height = Number(res?.height || 0) const now = Date.now() const visible = height > 0 // 防抖:如果高度没变化或时间间隔太短,忽略 if (height === lastHeight && (now - lastTime) < debounceDelay) { return } lastHeight = height lastTime = now // 保存待更新的状态 pendingUpdate = { height, visible } // 取消之前的更新 if (rafId !== null) { cancelAnimationFrame(rafId) } // 延迟执行更新,避免阻塞消息处理 rafId = requestAnimationFrame(() => { requestAnimationFrame(applyUpdate) }) }) set({ isInitialized: true }) }, cleanup: () => { console.log('清理全局键盘监听器') // @ts-ignore if (typeof Taro.offKeyboardHeightChange === 'function') { // @ts-ignore Taro.offKeyboardHeightChange() } set({ isInitialized: false, keyboardHeight: 0, isKeyboardVisible: false, listeners: new Set() }) } })) // 导出便捷的 hooks export const useKeyboardHeight = () => { const { keyboardHeight, isKeyboardVisible, addListener, initializeKeyboardListener } = useKeyboardStore() return { keyboardHeight, isKeyboardVisible, addListener, initializeKeyboardListener } }