2.4 Elements -- useElementBounding

2.4 Elements – useElementBounding

https://vueuse.org/core/useElementBounding/

作用

把一个html元素变成响应式盒子

官方示例

<template>
  <div ref="el" />
</template>

<script>
import { ref } from 'vue'
import { useElementBounding } from '@vueuse/core'

export default {
  setup() {
    const el = ref(null)
    const { x, y, top, right, bottom, left, width, height } = useElementBounding(el)

    return {
      el,
      /* ... */
    }
  }
}
</script>

无渲染组件用法如下:

<UseElementBounding v-slot="{ width, height }">
  Width: {{ width }}
  Height: {{ height }}
</UseElementBounding>

源码分析

核心是使用getBoundingClientRect获取target的信息。主要看哪些场景会触发update

官方示例中的元素可变大小,是通过css属性实现的: resize: both;

export function useElementBounding(
  target: MaybeComputedElementRef,
  options: UseElementBoundingOptions = {},
) {
  const {
    reset = true,
    windowResize = true,
    windowScroll = true,
    immediate = true,
  } = options

  const height = ref(0)
  const bottom = ref(0)
  const left = ref(0)
  const right = ref(0)
  const top = ref(0)
  const width = ref(0)
  const x = ref(0)
  const y = ref(0)

  function update() {
    const el = unrefElement(target)

    if (!el) {
      if (reset) {
        height.value = 0
        bottom.value = 0
        left.value = 0
        right.value = 0
        top.value = 0
        width.value = 0
        x.value = 0
        y.value = 0
      }
      return
    }

    /**
    * 核心API
    */
    const rect = el.getBoundingClientRect()

    height.value = rect.height
    bottom.value = rect.bottom
    left.value = rect.left
    right.value = rect.right
    top.value = rect.top
    width.value = rect.width
    x.value = rect.x
    y.value = rect.y
  }

  // target大小变化,触发update
  useResizeObserver(target, update)
  
  // target被销毁了,触发update
  watch(() => unrefElement(target), ele => !ele && update())

  // 页面滚动,触发update
  // passive: true,显式告诉浏览器,回调中不会阻止默认事件。这有利于减少浏览器等待时间,提高性能。
  if (windowScroll)
    useEventListener('scroll', update, { capture: true, passive: true })
  
  /// 页面大小变化,触发update
  if (windowResize)
    useEventListener('resize', update, { passive: true })

  tryOnMounted(() => {
    // 如果immediate,在onMounted之后,触发update
    if (immediate)
      update()
  })

  return {
    height,
    bottom,
    left,
    right,
    top,
    width,
    x,
    y,
    update,
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值