news 2026/4/14 19:37:49

51、在vue项目中获取页面元素位置与宽高

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
51、在vue项目中获取页面元素位置与宽高

目录

一、最常见做法:通过 ref 获取元素

Vue 3 写法

Vue 2 写法

二、获取元素位置与宽高的几种方式

1. 获取相对于视口的位置和实际渲染宽高

适合场景

2. 获取布局宽高

特点

3. 获取内容区可视宽高

特点

4. 获取内容总宽高

适合场景

5. 获取相对父级的位置

三、如果要获取“相对于整个页面”的位置

Vue 3 示例

四、为什么在 Vue 中要用 nextTick?

示例

面试表达

五、Vue 2 中怎么拿?

示例

六、实际项目里常见场景

1. 获取元素位置做吸顶

2. 判断元素是否进入可视区

3. 获取容器宽度做图表自适应

4. 判断内容是否溢出

七、如果是组件渲染后获取子组件内部元素怎么办?

方式1:子组件自己暴露方法

子组件

父组件

方式2:直接把 DOM ref 暴露出去

八、如果元素尺寸会变化,怎么实时监听?

Vue 3 示例

适合场景

九、如果是列表循环出来的元素怎么获取?

Vue 3 中可以函数式绑定

十、面试中怎么回答更好?

标准回答

十一、可直接背的精简面试版

十二、简洁代码模板

Vue 3 通用模板

十三、一句话总结


在 Vue 里获取页面元素位置和宽高,本质上还是操作 DOM,和原生 JS 一样,核心还是这些 API:

  • getBoundingClientRect()
  • offsetWidth / offsetHeight
  • clientWidth / clientHeight
  • scrollWidth / scrollHeight
  • offsetTop / offsetLeft

但在 Vue 里有一个关键点:

必须等 DOM 渲染完成后再去拿。

因为 Vue 是响应式更新的,数据变了不代表 DOM 立刻更新,所以如果你拿元素尺寸,通常要放在:

  • mounted
  • onMounted
  • nextTick

里。


一、最常见做法:通过ref获取元素

在 Vue 项目中,一般不会直接到处document.querySelector,更推荐用ref


Vue 3 写法

<template> <div ref="boxRef" class="box">内容</div> </template> <script setup> import { ref, onMounted } from 'vue' const boxRef = ref(null) onMounted(() => { const el = boxRef.value const rect = el.getBoundingClientRect() console.log('相对视口 top:', rect.top) console.log('相对视口 left:', rect.left) console.log('宽度:', rect.width) console.log('高度:', rect.height) }) </script> <style> .box { width: 200px; height: 100px; background: lightblue; } </style>

Vue 2 写法

<template> <div ref="box" class="box">内容</div> </template> <script> export default { mounted() { const el = this.$refs.box const rect = el.getBoundingClientRect() console.log('top:', rect.top) console.log('left:', rect.left) console.log('width:', rect.width) console.log('height:', rect.height) } } </script>

二、获取元素位置与宽高的几种方式


1. 获取相对于视口的位置和实际渲染宽高

最推荐:

const rect = el.getBoundingClientRect() console.log(rect.top) console.log(rect.left) console.log(rect.width) console.log(rect.height)

适合场景

  • 吸顶
  • 懒加载
  • 判断元素是否进入可视区
  • 弹层定位
  • 页面滚动联动

2. 获取布局宽高

console.log(el.offsetWidth) console.log(el.offsetHeight)

特点

包含:

  • content
  • padding
  • border

不包含:

  • margin

3. 获取内容区可视宽高

console.log(el.clientWidth) console.log(el.clientHeight)

特点

包含:

  • content
  • padding

不包含:

  • border
  • 滚动条

4. 获取内容总宽高

console.log(el.scrollWidth) console.log(el.scrollHeight)

适合场景

  • 判断内容是否溢出
  • 判断是否出现滚动条

5. 获取相对父级的位置

console.log(el.offsetTop) console.log(el.offsetLeft)

注意:

这是相对于offsetParent,不是相对于页面,也不是相对于视口。


三、如果要获取“相对于整个页面”的位置

getBoundingClientRect()拿到的是相对于视口的位置。
如果你要拿元素相对于整个文档的位置,要加滚动距离。


Vue 3 示例

<template> <div ref="boxRef" class="box">内容</div> </template> <script setup> import { ref, onMounted } from 'vue' const boxRef = ref(null) onMounted(() => { const el = boxRef.value const rect = el.getBoundingClientRect() const pageTop = rect.top + window.scrollY const pageLeft = rect.left + window.scrollX console.log('相对页面 top:', pageTop) console.log('相对页面 left:', pageLeft) }) </script>

四、为什么在 Vue 中要用nextTick

这是很重要的点。

因为 Vue 修改数据后,DOM 更新是异步批量更新的。
如果你刚改完数据立刻去拿元素尺寸,可能拿到的是旧值。


示例

<template> <div ref="boxRef" :style="{ width: width + 'px' }"></div> <button @click="changeWidth">修改宽度</button> </template> <script setup> import { ref, nextTick } from 'vue' const boxRef = ref(null) const width = ref(100) const changeWidth = async () => { width.value = 300 await nextTick() console.log('最新宽度:', boxRef.value.offsetWidth) } </script>

如果不加nextTick(),有可能拿到的还是旧宽度。


面试表达

在 Vue 中获取元素宽高时,除了使用原生 DOM API 外,还要注意时机问题。
一般首次获取放在mounted/onMounted,如果是数据更新后再获取,需要等nextTick,确保 DOM 已经完成更新。


五、Vue 2 中怎么拿?

Vue 2 一般通过this.$refs


示例

<template> <div> <div ref="box" :style="{ width: width + 'px' }"></div> <button @click="changeWidth">修改宽度</button> </div> </template> <script> export default { data() { return { width: 100 } }, methods: { changeWidth() { this.width = 300 this.$nextTick(() => { console.log(this.$refs.box.offsetWidth) }) } }, mounted() { console.log(this.$refs.box.offsetWidth) } } </script>

六、实际项目里常见场景


1. 获取元素位置做吸顶

const rect = el.getBoundingClientRect() if (rect.top <= 0) { console.log('元素到顶部了') }

2. 判断元素是否进入可视区

const rect = el.getBoundingClientRect() const inView = rect.top < window.innerHeight && rect.bottom > 0

3. 获取容器宽度做图表自适应

const width = containerRef.value.clientWidth chart.resize({ width })

4. 判断内容是否溢出

const el = boxRef.value const isOverflow = el.scrollWidth > el.clientWidth console.log(isOverflow)

七、如果是组件渲染后获取子组件内部元素怎么办?

如果元素在子组件里,通常有两种方式。


方式1:子组件自己暴露方法

子组件

<template> <div ref="innerRef" class="inner"></div> </template> <script setup> import { ref } from 'vue' const innerRef = ref(null) const getRect = () => { return innerRef.value.getBoundingClientRect() } defineExpose({ getRect }) </script>

父组件

<template> <Child ref="childRef" /> </template> <script setup> import { ref, onMounted } from 'vue' import Child from './Child.vue' const childRef = ref(null) onMounted(() => { const rect = childRef.value.getRect() console.log(rect) }) </script>

方式2:直接把 DOM ref 暴露出去

也可以,但一般不如暴露方法更好。


八、如果元素尺寸会变化,怎么实时监听?

如果你不是只拿一次,而是希望尺寸变化时自动更新,可以用ResizeObserver


Vue 3 示例

<template> <div ref="boxRef" class="box">内容</div> </template> <script setup> import { ref, onMounted, onBeforeUnmount } from 'vue' const boxRef = ref(null) let observer = null onMounted(() => { observer = new ResizeObserver((entries) => { for (const entry of entries) { console.log('宽度变化:', entry.contentRect.width) console.log('高度变化:', entry.contentRect.height) } }) observer.observe(boxRef.value) }) onBeforeUnmount(() => { observer && observer.disconnect() }) </script>

适合场景

  • 图表容器自适应
  • 弹窗内容高度变化
  • 响应式布局监听
  • 表格列宽变化

九、如果是列表循环出来的元素怎么获取?

在 Vue 里循环元素时,也可以配合ref


Vue 3 中可以函数式绑定

<template> <div v-for="(item, index) in list" :key="item.id" :ref="el => setItemRef(el, index)" > {{ item.name }} </div> </template> <script setup> import { ref, onMounted } from 'vue' const list = ref([ { id: 1, name: 'A' }, { id: 2, name: 'B' } ]) const itemRefs = ref([]) const setItemRef = (el, index) => { if (el) itemRefs.value[index] = el } onMounted(() => { itemRefs.value.forEach(el => { console.log(el.getBoundingClientRect()) }) }) </script>

十、面试中怎么回答更好?

如果面试问:

在 Vue 项目中怎么获取页面元素位置与宽高?

你不要只回答“用 ref”。

更好的回答应该是:


标准回答

在 Vue 项目里获取元素位置和宽高,本质上还是调用原生 DOM API,比如getBoundingClientRect()offsetWidthclientHeight等。
只是 Vue 里要注意获取时机,通常会通过ref拿到 DOM 节点,然后在mounted/onMounted里获取;如果是响应式数据更新后再获取,需要等nextTick,确保 DOM 已经更新完成。

如果我要获取元素相对于视口的位置和渲染后的宽高,我会优先用getBoundingClientRect()
如果是获取布局宽高,可以用offsetWidth/offsetHeight
如果是获取内容区域大小,可以用clientWidth/clientHeight

在实际项目中,如果元素尺寸会动态变化,我还会结合ResizeObserver做监听。


十一、可直接背的精简面试版

在 Vue 中获取页面元素位置和宽高,一般会先通过ref获取 DOM 元素,再结合原生 DOM API 获取。
比如:

  • getBoundingClientRect()获取相对于视口的位置和宽高
  • offsetWidth/offsetHeight获取包含 border 的布局尺寸
  • clientWidth/clientHeight获取内容区加 padding 的尺寸

需要注意的是,Vue 的 DOM 更新是异步的,所以首次获取一般放在mounted/onMounted,如果是数据更新后获取,要配合nextTick
如果元素大小会变化,还可以使用ResizeObserver监听。


十二、简洁代码模板


Vue 3 通用模板

<template> <div ref="elRef" class="box">内容</div> </template> <script setup> import { ref, onMounted, nextTick } from 'vue' const elRef = ref(null) onMounted(() => { const el = elRef.value console.log('offsetWidth:', el.offsetWidth) console.log('clientWidth:', el.clientWidth) const rect = el.getBoundingClientRect() console.log('top:', rect.top) console.log('left:', rect.left) console.log('width:', rect.width) console.log('height:', rect.height) }) // 数据更新后获取 async function getLatestRect() { await nextTick() const rect = elRef.value.getBoundingClientRect() console.log(rect) } </script>

十三、一句话总结

在 Vue 项目中获取元素位置和宽高,核心是ref + DOM API,关键是选对生命周期和在更新后使用nextTick

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 19:37:17

告别‘玄学’调优:SOME/IP实战中UDP与TCP绑定的选择指南(含性能对比)

SOME/IP协议中UDP与TCP绑定的工程实践指南 在汽车电子系统开发中&#xff0c;通信协议的选择往往决定了整个系统的实时性和可靠性表现。SOME/IP作为车载网络中的核心中间件协议&#xff0c;其UDP与TCP两种传输绑定方式各有特点&#xff0c;开发者需要根据具体场景做出合理选择。…

作者头像 李华
网站建设 2026/4/14 19:35:25

告别FLAASH!用ENVI的快速大气校正工具处理Landsat数据,5分钟出结果

5分钟极速处理Landsat数据&#xff1a;ENVI快速大气校正实战指南 当项目周期压缩到以小时计算&#xff0c;或是需要快速验证数据质量时&#xff0c;传统FLAASH大气校正的复杂参数设置往往成为效率瓶颈。最近在遥感数据处理社区中&#xff0c;越来越多的工程师开始采用ENVI内置的…

作者头像 李华
网站建设 2026/4/14 19:33:51

操作系统原理关联:Graphormer模型推理过程中的内存与进程调度优化

Graphormer模型推理性能优化&#xff1a;操作系统层面的深度调优实践 1. 从操作系统视角看模型推理瓶颈 Graphormer作为图神经网络的重要模型&#xff0c;在实际部署中常常面临推理性能不稳定的问题。通过长期的生产环境观察&#xff0c;我们发现这些性能问题往往不是模型本身…

作者头像 李华
网站建设 2026/4/14 19:30:48

【Matlab】MATLAB教程:小波去噪原理、wden函数实操及信号噪声去除应用

本文基于MATLAB R2020b编写(兼容R2018及以上版本),聚焦小波去噪核心原理、wden函数实操细节、信号噪声去除工程应用三大模块,构建“理论基础→函数实操→案例应用→工程拓展”的完整闭环。内容兼顾入门性与实用性,无需深入推导复杂数学公式,重点突出MATLAB实操步骤,结合…

作者头像 李华
网站建设 2026/4/14 19:29:54

揭秘百度搜索算法逆向工程:技术解析与实战策略

百度搜索算法逆向思考技术文章大纲百度搜索算法的核心机制爬虫与索引构建&#xff1a;网页抓取策略、内容解析、索引结构设计排序模型&#xff1a;PageRank的变体、机器学习排序&#xff08;如BERT、RankNet&#xff09;用户意图识别&#xff1a;查询理解、实体识别、个性化因素…

作者头像 李华