IntersectionObserver 在 Vue 中监听元素进入视口不生效?

永臣 ☘︎ 阅读 17

我在 Vue 3 项目里用 IntersectionObserver 做懒加载,但回调一直没触发。页面滚动时完全没反应,控制台也没报错。我试过把 root 设为 null,threshold 改成 0 或 1 都不行,是不是 observer 没正确绑定到 DOM 元素上?

下面是简化后的代码:

<template>
  <div ref="targetRef" style="height: 200px; background: #eee;">观察目标</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const targetRef = ref(null)

onMounted(() => {
  const observer = new IntersectionObserver((entries) => {
    console.log('触发了!', entries[0].isIntersecting)
  })
  observer.observe(targetRef.value)
})
</script>
我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
设计师素香
问题在于你的目标元素初始就在视口内,IntersectionObserver 默认只在状态改变时触发回调。你需要用 isIntersecting 来判断当前是否相交。

另外 observer 实例没保存下来会被垃圾回收,而且目标元素得在视口外才能测试。

改一下:

<template>
<div style="height: 100vh;"></div>
<div ref="targetRef" style="height: 200px; background: #eee;">观察目标</div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const targetRef = ref(null)
let observer = null

onMounted(() => {
observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('进入视口了!')
// 这里执行你的懒加载逻辑
}
})
}, {
threshold: 0
})

if (targetRef.value) {
observer.observe(targetRef.value)
}
})

onUnmounted(() => {
observer && observer.disconnect()
})
</script>


关键点:加一个高度为 100vh 的 div 把目标元素顶到视口外面去,这样滚动时才能触发回调。observer 实例保存到变量里并在组件销毁时 disconnect,这是规范做法。

如果还是不行,检查一下页面是否有滚动条,父元素有没有 overflow: hidden 之类的属性阻挡了。
点赞
2026-03-11 15:01