1. uniapp获取dom高度不准确的问题
在进行uniapp开发的过程中,我们常常需要获取dom元素的高度来进行相应的样式调整,然而实际中我们发现有时候获取到的dom高度不准确,导致页面展示和设计脱离,影响用户体验。那么uniapp获取dom高度不准确的问题是怎么引起的呢?
1.1 引起问题的原因
首先,我们需要了解一下获取dom高度的原理。在浏览器中每个dom元素都有自己的clientHeight,这个值代表了该元素在盒模型里占据的空间大小,即元素高度。而在客户端中,这个clientHeight的值是无法直接获取到的,因此我们需要通过其他手段来获取。通常我们使用uniapp提供的API:
const query = uni.createSelectorQuery()
query.select('#dom').boundingClientRect(data => {
console.log(data.height)
}).exec()
其实本质上其依然是利用了原生API进行计算的,但问题便在这里,这种方式获取到的实际上并不是我们所期望的高度值,原因如下:
1.1.1 dom元素未渲染完全
利用uniapp提供的API进行获取高度时,如果dom元素内部存在异步操作,如图片加载等等,那么页面渲染流程中所获取到的高度值往往是不准确的。这便是因为渲染引擎在计算高度时还未完全完成。而且,根据我个人的实践,一般情况下计算误差往往会偏小,甚至零,但是一旦在同一个页面内经常做dom高度获取操作,出现一次误差,误差会累积,导致后续的dom高度获取都出现问题。
1.1.2 高度计算存在误差
其实还有一个比较重要的原因是,在客户端中,获取元素高度使用的是window.getComputedStyle方法,而这个方法返回的是字符串,类似'65px',而不是数值类型。由于不同的设备像素比例,有时候会出现计算误差,导致一些元素的高度计算不准确。
1.1.3 存在内外边距
在进行dom高度计算时,还需要考虑到元素的 padding 和 margin。这两个属性会导致width计算不准确,因为这两个值的计算未加入到测量中。
1.2 解决方法
有了上述问题的了解,我们就可以针对性地来解决这些问题了。下面我来介绍下解决方法。
1.2.1 设置定时器进行等待
我们可以使用setTimeout函数来延迟获取dom元素高度的时机,以确保页面元素加载完成:
setTimeout(() => {
const query = uni.createSelectorQuery()
query.select('#dom').boundingClientRect(data => {
console.log(data.height)
}).exec()
})
我们需要注意的是,由于uni.createSelectorQuery()是异步方法,因此不能直接使用async + await方式。
1.2.2 使用getBoundingClientRect方法
由于uniapp API获取height存在一定的问题,我们可以采用原生API进行高度获取。其中getBoundingClientRect方法可以用于获取dom元素的宽、高等信息。下面是示例代码:
// 获取dom元素
const el = document.getElementById('dom')
const { height } = el.getBoundingClientRect()
console.log(height)
这种方式也是利用了原生API计算元素高度,应该是比较准确的,但同时也会存在上述计算误差的问题。
1.2.3 实时计算内外边距
在进行dom高度获取时,考虑到padding和margin的影响,我们可以采用实时计算这两个值,以确保高度准确无误。
/**
* 计算dom元素高度(包含padding和margin)
* @param {HTMLElement} el 当前dom
* @returns {number} 高度
*/
function getDomHeight(el) {
let height = 0
const style = getComputedStyle(el)
const marginTop = Number(style.getPropertyValue('margin-top').split('px')[0])
const marginBottom = Number(style.getPropertyValue('margin-bottom').split('px')[0])
const paddingTop = Number(style.getPropertyValue('padding-top').split('px')[0])
const paddingBottom = Number(style.getPropertyValue('padding-bottom').split('px')[0])
height = el.offsetHeight + marginTop + marginBottom + paddingTop + paddingBottom
return height
}
// 获取dom元素高度(包含padding和margin)
const el = document.getElementById('dom')
const height = getDomHeight(el)
console.log(height)
2. 总结
针对uniapp获取dom高度不准确的问题,我们介绍了其原因和解决方法,可以通过设置定时器、使用getBoundingClientRect方法以及实时计算内外边距等方式来获取准确的dom高度。在使用过程中,还需要注意积累误差的问题,提高代码可复用性和性能。