在开发IM的项目过程当中,常常会有出现一些须要计算DOM高度,而后超出若干行隐藏等需求。不少时候,须要计算高度的DOM元素都是动态生成的,咱们没法在数据渲染前获取到它的高度。javascript
若是没有任何交互,咱们能够经过CSS来实现这个需求。可是,若是咱们须要使用JavaScript来实现一些交互(好比消息渲染时,超过2行显示某个特定按钮等),则只能经过JavaScript来进行实现。我在这里介绍一种经过JavaScript来对元素高度进行计算的方法,但愿可以给你们提供一些思路。html
根据前端的基本常识,在内存中未渲染的DOM元素是没法获取到高度的,所以咱们有两个方向来解决这个难题:前端
如下的实现方案将根据上面所选择的技术方案来进行实现。java
此方案无需多言,就是经过字的总数、行高和每一行可以容下的字的个数进行估算等。在项目最开始时,我采用的就是这个方案。具体实现代码较为简单,所以不在本文中提供示例。node
此方案实现简单,基本不须要任何技术成本。算法
只适用于等宽文字,若是出现富文本(好比有emoji或者图片表情等高度不一致)的状况,则没法适用。若是字体为非等宽字体或者存在\n
之类的换行符或者是\t
之类的制表符时,估算的准确度也会降低。浏览器
顾名思义,此方案就是先不考虑DOM元素行数逻辑,直接将全部的DOM节点所有渲染到页面中,渲染完成后再对进行后续逻辑判断。获取高度后页面行数计算将在后面统一讲解。app
此方案经过直接在实际场景的页面上渲染后进行高度计算,所以计算精准,不存在任何误差。同时,此方案实现起来也较为简单,只须要将业务逻辑执行时间后延,并不须要开发额外的代码。布局
该方案缺点也比较明显,因为是先渲染后处理,所以页面DOM元素会出现重绘和重排,致使页面闪动,从而影响用户的体验。字体
该方案的灵感来自于上一个方案。由于在实际的页面中进行计算可以保证页面高度计算没有任何偏差,所以咱们须要一个实际的场景,让浏览器来帮助咱们进行高度计算。同时,咱们又不能在具体的功能页面中先渲染后计算,所以咱们能够直接建立一个与实际页面中如出一辙的容器来进行高度计算。这样咱们既可以精确计算,又可以不影响用户体验。
具体实现的代码能够参考以下示例:
export default function getLines(element = 'div', style = {}, html = '') {
let node = document.createElement(element);//建立一个新容器
let length;
each(style, (element, index) => {
node.style[index] = element;//将传入的style遍历后赋值给新容器
});
node.innerHTML = html;
document.body.appendChild(node);//须要将新容器挂载到DOM中,浏览器才会进行高度计算
let height = global.getComputedStyle(node).height;
document.body.removeChild(node);//须要将镜像DOM进行移除
if (height.indexOf('px') > 0) {
length = parseInt(height.split('px')[0]);
} else {
length = 0;
}
return length;
}
复制代码
该方案基本上继承了第二个方案的全部优势——精确计算,无偏差,而且避免了出现页面闪动的状况。
此方案仍然存在一些问题,将新容器挂载到document元素上时,可能会引起DOM元素的从新渲染,极低几率会影响页面布局。同时,属性值等须要本身手动传入,而不是利用现成的容器,比较费时费力。
使用cloneNode方法来对现有的容器进行clone,咱们能够省去输入样式的麻烦,同时可以精确保证两个容器彻底一致。
在实践过程当中,在append之后马上remove镜像DOM节点,不会对页面产生任何影响。若是担忧添加时会给页面形成闪动效果,能够给镜像DOM添加上position:fixed;visibility:hidden;z-index:-999;
属性,可以让镜像DOM在append到页面时,不会影响当前页面的任何布局。
为何咱们不使用display:none
来实现上述效果呢?由于在使用了该属性后,window.getComputedStyle
获取的高度将变为auto
。同理,若是元素的display
属性为inline
时,也会出现相似的效果,所以咱们须要将display
指定为block
或者inline-block
。
理论上咱们的容器都应该为块级元素,不然计算高度的意义也就不存在了。所以在容器clone时只须要留意便可,不须要从新指定。
两个优化点通过实践已经证实可行,具体代码就不附上了,若是有须要的能够给我留言~~
目前,经过高度来计算行数并无什么比较好的方法,通常是经过line-height
两个属性来进行计算。
若是line-height
为倍数的话,则还须要font-size
属性来肯定具体高度。
具体算法为:总高度 / 每一行高度 = 行数
而每一行高度则经过line-height
或者line-height
* font-size
肯定。
获取动态元素的高度一直都是IM项目中的一个重要需求,本身在这个方面也踩了许多坑,所以写了这一篇博客来进行记录,同时其余人若是看到了也能够避免一些常见问题。
因为此方案较为繁琐,同时容易留下很多坑,不太推荐使用此方法,仍是建议经过产品方案等其余手段规避此方案。