实现vueuse中useElementVisibility的自定义hook

在vueuse我看到一个很好用的方法useElementVisibility,它可以帮助我们判断元素是否在屏幕的可视区域内,可以用来懒加载图片列表或一些其他功能。实现它的核心代码就几行,在实现之前需要了解一些属性。

Element.getBoundingClientRect()

domRect = element.getBoundingClientRect();

它的返回值是一个DOMRect对象,这个对象是一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有lefttoprightbottomxywidth, 和 height这几个以像素为单位的只读属性用于描述整个边框。除了width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

 

 知道这些后就可以来实现效果了。

函数需要接收一个ref的节点,作为判断位置的参数

创建一个ref<boolean>值用来记录元素是否显示

const elementIsVisibility = ref(false)

创建一个函数来判断元素位置

  const testBounding = () => {
    
    // 判断传入是否有值
    if (!element.value) {
      elementIsVisibility.value = false
    } else {
      const rect = element.value.getBoundingClientRect()

      elementIsVisibility.value = (
        rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&
        rect.bottom >= 0 &&
        rect.right >= 0
      )
    }
  }

这里也可以用

  • top 大于等于 0
  • left 大于等于 0
  • bottom 小于等于视窗高度
  • right 小于等于视窗宽度
function isInViewPort(element) {
  const viewWidth = window.innerWidth || document.documentElement.clientWidth;
  const viewHeight = window.innerHeight || document.documentElement.clientHeight;
  const {
    top,
    right,
    bottom,
    left,
  } = element.getBoundingClientRect();

  return (
    top >= 0 &&
    left >= 0 &&
    right <= viewWidth &&
    bottom <= viewHeight
  );
}

判断后在Vue生命周期中给window添加scroll监听

onMounted(() => {
    useEventListener('scroll', testBounding, { capture: false, passive: true })
})

这里passive: true可以改善滚屏性能,具体可以在MDN上查看。

最后将变量返回

import { ref, onMounted } from "vue";
import { useEventListener } from "./useEventListener";

export function useElementVisibility(
  element//传入需要判断的节点的ref
) {
  // const window = Window
  const document = window.document
  const elementIsVisibility = ref(false)
  const testBounding = () => {
    
    // 判断传入是否有值
    if (!element.value) {
      elementIsVisibility.value = false
    } else {
      const rect = element.value.getBoundingClientRect()

      elementIsVisibility.value = (
        rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&
        rect.bottom >= 0 &&
        rect.right >= 0
      )
    }
  }
  onMounted(() => {
    useEventListener('scroll', testBounding, { capture: false, passive: true })
  })

  return elementIsVisibility
}

 

posted @ 2022-01-28 22:58  Bob康康  阅读(623)  评论(0)    收藏  举报