import { ref, onMounted, onUnmounted } from 'vue' export function useElementSize(targetSelector) { const width = ref(0) const height = ref(0) let observer = null const updateSize = () => { const query = uni.createSelectorQuery() query.select(targetSelector).boundingClientRect(rect => { if (rect) { width.value = rect.width height.value = rect.height } }).exec() } onMounted(() => { updateSize() // 尝试使用 ResizeObserver(部分小程序基础库支持) if (uni.createIntersectionObserver) { observer = uni.createIntersectionObserver(this, { observeAll: true }) observer.relativeToViewport().observe(targetSelector, updateSize) } }) onUnmounted(() => { observer?.disconnect() }) return { width, height, updateSize } } export function useEventListener(target, event, handler) { // 组件内事件 if (target.$on) { target.$on(event, handler) const stop = () => target.$off(event, handler) onUnmounted(stop) return stop } // 全局事件(需配合 uni.$emit 使用) else { uni.$on(event, handler) const stop = () => uni.$off(event, handler) onUnmounted(stop) return stop } } export function useRafFn(fn, { immediate = true } = {}) { let isActive = false let timerId = null const loop = () => { if (!isActive) return fn() timerId = setTimeout(loop, 16) // 模拟 60fps } const start = () => { if (isActive) return isActive = true loop() } const stop = () => { isActive = false clearTimeout(timerId) } onUnmounted(stop) immediate && start() return { start, stop } }