Vue3 实战:用 Intersection Observer

2025-03-16  本文已影响0人  一颗得道的仙丹

ts实现

import { ref, onMounted, onBeforeUnmount } from 'vue'

/**
 * 用于观察元素是否进入视口的组合式函数
 * @param {string} targetId - 要观察的目标元素的 ID
 * @param {Object} options - 配置选项
 * @param {Element | null} options.root - 观察视口,默认为 null
 * @param {string} options.rootMargin - 视口的边距,默认为 '0px'
 * @param {number} options.threshold - 多少比例可视区域进入视口时触发回调,默认为 0.1
 * @returns {Object} - 包含一个响应式的 isVisible 属性,用于表示目标元素是否进入视口
 */
export function useIntersectionObserver(
  targetId: string,
  options: {
    root?: Element | null
    rootMargin?: string
    threshold?: number
  },
) {
  const isVisible = ref(false)
  const defaultOptions = {
    root: null,
    rootMargin: '0px',
    threshold: 0.1,
  }
  const finalOptions = { ...defaultOptions, ...options }
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        isVisible.value = true
        setTimeout(() => {
          observer.unobserve(entry.target)
        }, 100)
      }
    })
  }, finalOptions)

  onMounted(() => {
    const targetElement = document.getElementById(targetId)
    if (!targetElement) {
      // console.error(`未找到 ID 为 "${targetId}" 的元素`)
      return
    }
    observer.observe(targetElement)
  })

  onBeforeUnmount(() => {
    observer.disconnect()
  })

  return {
    isVisible,
  }
}

页面实现

import { useIntersectionObserver } from '@/实际路径/useIntersectionObserver'
const wmAnimationEffectsRef = ref<HTMLElement | null>(null) // 绑定的ref实例
// 使用组合式函数监听元素可见性
const { isVisible: isWmAnimationEffectsVisible } = useIntersectionObserver(wmAnimationEffectsRef)
<style>
// 初始状态下隐藏元素,设置透明度为 0
.test {
   opacity: 0;
  transition: opacity 0.5s ease;
}
// 当元素进入视口时,添加 is-visible 类,显示元素
.test.is-visible {
  opacity: 1;
  transition: opacity 0.5s ease;
}
<style>
// 模板绑定
<template>
<div class="test"  
:class="{ 'is-visible': isWmAnimationEffectsVisible }" 
ref="wmAnimationEffectsRef"><div>
</template>
上一篇 下一篇

猜你喜欢

热点阅读