首页 前端知识 Vue 3获取DOM元素的大小以及相对于视口的位置的getBoundingClientRect属性

Vue 3获取DOM元素的大小以及相对于视口的位置的getBoundingClientRect属性

2024-07-20 17:07:38 前端知识 前端哥 503 66 我要收藏

在Vue 3中,可以使用ref来获取DOM元素的getBoundingClientRect属性。
如果元素已挂载,我们使用 getBoundingClientRect 方法来获取元素的位置和大小信息。这个方法返回一个对象,其中包含了 left、top、right、bottom 等属性,这些属性表示元素相对于其最近的滚动祖先(通常是视口)的位置。
这里是一个简单的例子:

<template>
  <div ref="boxRef">Hello World</div>
</template>

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

const boxRef = ref(null); //创建一个响应式引用boxRef,它将指向div元素
  //在onMounted钩子中,我们确保当组件挂载后获取这个元素的getBoundingClientRect属性。这个属性包含了元素的大小以及相对于视口的位置。
onMounted(() => {
  if (boxRef.value) {
    const rect = boxRef.value.getBoundingClientRect();
    console.log(rect);

  }
});
</script>

如果你想要监听元素上的右键点击事件,并获取该元素的位置,你可以使用@contextmenu.prevent来监听右键点击事件,并使用getBoundingClientRect方法来获取元素的位置。
这里是如何实现的一个例子:

<template>
  <div ref="myElement" @contextmenu.prevent="handleRightClick">
    右键点击我
  </div>
</template>

<script setup>
import { ref } from 'vue';

const myElement = ref(null);

function handleRightClick(event) {
  if (myElement.value) {
  //获取了元素的位置信息rect,它包含了元素相对于视口的位置和大小。
  //使用event.clientX和event.clientY来获取鼠标指针相对于浏览器视口的位置,并从中减去元素的位置,从而得到鼠标指针相对于元素左上角的位置。
    const rect = myElement.value.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;
    
    console.log('元素位置:', rect);
    console.log('相对于元素的点击位置:', { x, y });

    // 阻止浏览器默认上下文菜单显示
    event.preventDefault();
//额外例子 如果你获取offsetWidth值 如下:
 const offsetWidth = myElement.value.offsetWidth;
    console.log('元素的offsetWidth:', offsetWidth);
  }
}
</script>

请注意,getBoundingClientRect返回的位置是相对于视口的,而不是相对于文档的。如果你需要相对于整个文档的位置,你需要将视口滚动偏移量考虑进去。这通常涉及到使用window.scrollX和window.scrollY(或者document.documentElement.scrollLeft和document.documentElement.scrollTop)来获取这些值,并将它们加到rect.left和rect.top上。

在Vue 3中,如果你有一个通过v-for循环渲染的元素列表,并且 你想要在右键点击这些元素时获取它们的位置,你可以为每个元素添加一个唯一的引用,并在事件处理函数中通过该引用获取元素的位置。

以下是一个示例,展示了如何为循环渲染的元素添加右键点击事件,并获取它们的位置:

<template>
  <div>
    <div
      v-for="(item, index) in items"
      :key="item.id"
      :ref="`itemRef${index}`"
      @contextmenu.prevent="handleRightClick(index, $event)"
      style="margin-bottom: 10px; padding: 10px; background-color: lightgray;"
    >
      Item {{ item.id }}
    </div>
  </div>
</template>

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

const items = ref([
  { id: 1 },
  { id: 2 },
  { id: 3 },
  // ...其他项目
]);

const itemRefs = ref({}); // 存储所有项目的引用

onMounted(() => {
  // 假设你需要在组件挂载后做一些事情,比如为动态生成的ref添加事件监听器等
});

function handleRightClick(index, event) {
  const refName = `itemRef${index}`;
  const itemElement = itemRefs.value[refName];

  if (itemElement) {
    const rect = itemElement.getBoundingClientRect();
    console.log('元素位置:', rect);
    console.log('相对于元素的点击位置:', {
      x: event.clientX - rect.left,
      y: event.clientY - rect.top
    });
  }
}
</script>

在这个例子中,我们为每个循环渲染的元素创建了一个唯一的引用名称,通过拼接字符串"itemRef"和当前元素的索引index来实现。然后,在handleRightClick函数中,我们使用这个引用名称来获取对应的DOM元素,并调用getBoundingClientRect来获取元素的位置。

请注意,itemRefs是一个响应式对象,用于存储所有动态生成的ref。当Vue渲染这些元素时,每个元素的ref都会被自动添加到itemRefs对象中,并且可以使用它们的引用名称来访问。

此外,@contextmenu.prevent指令用于监听右键点击事件,并阻止默认的上下文菜单显示。$event是Vue的特殊变量,代表原生DOM事件对象,你可以用它来获取鼠标的位置等信息。

如果上述循环绑定的ref还是找不到元素 ,可以试试写法
:ref=“el => { if (el) itemRefs.value[index] = el; }”
代码如下:

<div
      v-for="(item, index) in items"
      :key="item.id"
      :ref="el => { if (el) itemRefs.value[index] = el; }"
      style="margin-bottom: 10px; padding: 10px; background-color: lightgray;"
    >
      Item {{ item.id }}
    </div>
...
// 使用 reactive 来创建一个响应式对象,用于存储所有元素的引用
const itemRefs = reactive({});

onMounted(() => {
  // 组件挂载后,你可以访问每个元素的引用
  for (const index in itemRefs) {
    if (itemRefs.hasOwnProperty(index) && itemRefs[index]) {
      const rect = itemRefs[index].getBoundingClientRect();
      console.log(`Item ${index} 位置:`, rect);
    }
  }
});

请确保你的项目已经正确设置,并且你正在使用Vue 3的Composition API语法。如果你的项目配置有所不同,可能需要进行一些调整来使这段代码正常工作。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/14007.html
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!