79 lines
1.7 KiB
JavaScript
79 lines
1.7 KiB
JavaScript
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 }
|
||
} |