mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-03 04:26:36 +08:00
重构核心模块并同步更新项目配置与相关实现
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { useEffect, useRef, type RefObject } from 'react'
|
||||
|
||||
const DEFAULT_ROOT_MARGIN = '480px 0px'
|
||||
|
||||
/**
|
||||
* 元素首次进入滚动容器附近时触发一次。用于媒体库预览的按需加载。
|
||||
*/
|
||||
export function useInViewOnce<T extends Element>(
|
||||
onVisible: () => void,
|
||||
rootMargin = DEFAULT_ROOT_MARGIN,
|
||||
): RefObject<T> {
|
||||
const ref = useRef<T>(null)
|
||||
const callbackRef = useRef(onVisible)
|
||||
|
||||
useEffect(() => {
|
||||
callbackRef.current = onVisible
|
||||
}, [onVisible])
|
||||
|
||||
useEffect(() => {
|
||||
const element = ref.current
|
||||
if (!element) return
|
||||
|
||||
if (typeof IntersectionObserver === 'undefined') {
|
||||
callbackRef.current()
|
||||
return
|
||||
}
|
||||
|
||||
const root = document.getElementById('app-main-scroll')
|
||||
let fired = false
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (fired || !entries.some((entry) => entry.isIntersecting)) return
|
||||
fired = true
|
||||
observer.disconnect()
|
||||
callbackRef.current()
|
||||
},
|
||||
{ root, rootMargin, threshold: 0.01 },
|
||||
)
|
||||
observer.observe(element)
|
||||
return () => observer.disconnect()
|
||||
}, [rootMargin])
|
||||
|
||||
return ref
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
|
||||
/**
|
||||
* 合并短时间内进入视口的预览请求,避免每个卡片各发一次 HTTP 请求。
|
||||
* 回调放在 ref 中,调用方每次渲染传新的闭包也不会重建定时器。
|
||||
*/
|
||||
export function useLazyPreviewBatch(
|
||||
onNeedPreviews?: (ids: string[]) => void,
|
||||
delayMs = 48,
|
||||
) {
|
||||
const pendingRef = useRef<Set<string>>(new Set())
|
||||
const timerRef = useRef<number | null>(null)
|
||||
const callbackRef = useRef(onNeedPreviews)
|
||||
|
||||
useEffect(() => {
|
||||
callbackRef.current = onNeedPreviews
|
||||
}, [onNeedPreviews])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timerRef.current !== null) {
|
||||
window.clearTimeout(timerRef.current)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return useCallback((id: string) => {
|
||||
if (!id || !callbackRef.current) return
|
||||
pendingRef.current.add(id)
|
||||
if (timerRef.current !== null) return
|
||||
timerRef.current = window.setTimeout(() => {
|
||||
timerRef.current = null
|
||||
const ids = Array.from(pendingRef.current)
|
||||
pendingRef.current.clear()
|
||||
if (ids.length > 0) {
|
||||
callbackRef.current?.(ids)
|
||||
}
|
||||
}, delayMs)
|
||||
}, [delayMs])
|
||||
}
|
||||
Reference in New Issue
Block a user