2024-04-28 10:10:03 +08:00

81 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { watch, unref, Ref } from "../vue"
// #ifdef APP-NVUE
// const dom = weex.requireModule('dom')
// const dom = uni.requireNativePlugin('dom')
// #endif
interface UseIntersectionObserverOptions {
root ?: string; // 观察器的根元素选择器字符串
rootMargin ?: {
top ?: number; // 根元素顶部边距
bottom ?: number; // 根元素底部边距
left ?: number; // 根元素左侧边距
right ?: number; // 根元素右侧边距
}; // 根元素的边距
thresholds ?: any[]; // 交叉比例数组,用于指定何时触发回调函数
context ?: any; // 上下文对象,用于指定观察器的上下文
initialRatio ?: number; // 初始的交叉比例
observeAll ?: boolean; // 是否同时观察所有交叉对象
}
/**
* 使用 Intersection Observer 观察元素可见性的自定义钩子函数
* @param {Ref<string> | string} target - 目标元素,可以是一个字符串或 ref 对象
* @param {(result: UniNamespace.ObserveResult) => void} callback - 回调函数,当目标元素的可见性发生变化时调用
* @param {UseIntersectionObserverOptions} options - 可选的配置参数
* @returns {Object} - 包含 stop 方法的对象,用于停止观察
*/
export function useIntersectionObserver(
target : Ref<string> | string,
callback : (result : UniNamespace.ObserveResult) => void,
options : UseIntersectionObserverOptions = {}) {
const {
root, // 观察器的根元素选择器
rootMargin = { top: 0, bottom: 0 }, // 根元素的边距默认为顶部和底部都为0
thresholds = [0], // 交叉比例数组,默认为[0]
initialRatio = 0, // 初始交叉比例默认为0
observeAll = false, // 是否同时观察所有交叉对象默认为false
context // 上下文对象,用于指定观察器的上下文
} = options
const noop = () => { }; // 空函数,用于初始化 cleanup
let cleanup = noop; // 清理函数,用于停止 Intersection Observer 的观察
const stopWatch = watch(() => ({ el: unref(target), root: unref(root) }), ({ el, root }) => {
if (!el) {
return
}
// #ifndef APP-NVUE
// 创建 Intersection Observer 实例
const observer = uni.createIntersectionObserver(context, { thresholds, initialRatio, observeAll })
if (root) {
// 相对于根元素设置边界
observer.relativeTo(root, rootMargin)
} else {
// 相对于视口设置边界
observer.relativeToViewport(rootMargin)
}
// 观察目标元素的可见性变化
observer.observe(el, callback)
cleanup = () => {
// 停止观察
observer.disconnect()
// 将 cleanup 函数重置为空函数
cleanup = noop
}
// #endif
// #ifdef APP-NVUE
// dom.getComponentRect(el, (res) => {
// console.log('res', res)
// })
// #endif
}, { immediate: true, flush: 'post' })
const stop = () => {
// 调用 cleanup 函数停止观察
cleanup && cleanup()
// 停止 watch
stopWatch && stopWatch()
}
return { stop }
}