useIntersectionObserver.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { ref, onMounted, onUnmounted, nextTick } from 'vue'
  2. /**
  3. * @description: 检测一个元素是否可见或者两个元素是否相交
  4. * @param {*} selector 元素选择器
  5. * @param {*} opts.scope 指定某个范围,因为 dom 操作可能会监听到别的组件的元素
  6. * @param {*} opts.multiple 监听多个元素时需传 true
  7. * @param {*} opts.handler 自定义返回的 entries 格式
  8. * @param {*} opts.options 构建 IntersectionObserver 实例的第二个参数 { root, rootMargin, threshold}
  9. * @return {intersectionObserver, entries} entries 即变动的元素信息
  10. */
  11. export default function useIntersectionObserver (selector, opts = {}) {
  12. const intersectionObserver = ref()
  13. const entries = ref([])
  14. onMounted(() => {
  15. nextTick(() => {
  16. const { scope = 'body', handler, options = {}, multiple = false } = opts
  17. intersectionObserver.value = new IntersectionObserver(function (entry) {
  18. entries.value = handler ? handler(entry) : entry
  19. }, options)
  20. let el
  21. const scopeEl = document.querySelector(scope)
  22. if (multiple) {
  23. el = scopeEl.querySelectorAll(selector)
  24. el?.forEach?.(item => {
  25. intersectionObserver.value.observe(item)
  26. })
  27. } else {
  28. el = scopeEl.querySelector(selector)
  29. intersectionObserver.value.observe(el)
  30. }
  31. })
  32. })
  33. onUnmounted(() => {
  34. intersectionObserver.value.disconnect()
  35. })
  36. return {
  37. intersectionObserver,
  38. entries
  39. }
  40. }