背景

在开发IM的项目过程中,经常会有出现一些需要计算DOM高度,然后超出若干行隐藏等需求。很多时候,需要计算高度的DOM元素都是动态生成的,我们无法在数据渲染前获取到它的高度。

如果没有任何交互,我们可以通过CSS来实现这个需求。但是,如果我们需要使用JavaScript来实现一些交互(比如消息渲染时,超过2行显示某个特定按钮等),则只能通过JavaScript来进行实现。我在这里介绍一种通过JavaScript来对元素高度进行计算的方法,希望能够给大家提供一些思路。

技术方案

根据前端的基本常识,在内存中未渲染的DOM元素是无法获取到高度的,因此我们有两个方向来解决这个难题:

  1. 通过字数对行数进行估算。
  2. 将元素渲染后进行高度测算 。

实现方案

以下的实现方案将根据上面所选择的技术方案来进行实现。

通过字数进行估算

方案

此方案无需多言,就是通过字的总数、行高和每一行能够容下的字的个数进行估算等。在项目最开始时,我采用的就是这个方案。具体实现代码较为简单,因此不在本文中提供示例。

优点

此方案实现简单,基本不需要任何技术成本。

缺点

只适用于等宽文字,如果出现富文本(比如有emoji或者图片表情等高度不一致)的情况,则无法适用。如果字体为非等宽字体或者存在\n之类的换行符或者是\t之类的制表符时,估算的准确度也会下降。

在DOM渲染后进行操作

方案

顾名思义,此方案就是先不考虑DOM元素行数逻辑,直接将所有的DOM节点全部渲染到页面中,渲染完成后再对进行后续逻辑判断。获取高度后页面行数计算将在后面统一讲解。

优点

此方案通过直接在实际场景的页面上渲染后进行高度计算,因此计算精准,不存在任何偏差。同时,此方案实现起来也较为简单,只需要将业务逻辑执行时间后延,并不需要开发额外的代码。

缺点

该方案缺点也比较明显,由于是先渲染后处理,因此页面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元素的重新渲染,极低概率会影响页面布局。同时,属性值等需要自己手动传入,而不是利用现成的容器,比较费时费力。

方案再优化

利用现有DOM容器

使用cloneNode方法来对现有的容器进行clone,我们可以省去输入样式的麻烦,同时能够精确保证两个容器完全一致。

隐藏镜像DOM

在实践过程中,在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项目中的一个重要需求,自己在这个方面也踩了许多坑,因此写了这一篇博客来进行记录,同时其他人如果看到了也可以避免一些常见问题。

由于此方案较为繁琐,同时容易留下不少坑,不太推荐使用此方法,还是建议通过产品方案等其他手段规避此方案。

IM应用中如何计算富文本的高度相关推荐

  1. [翻译] DTCoreText 从HTML文档中创建富文本

    DTCoreText 从HTML文档中创建富文本 https://github.com/Cocoanetics/DTCoreText 注意哦亲,DTRichTextEditor 这个组件是收费的,不贵 ...

  2. html缩略文本,列表中展示富文本的缩略内容

    列表中显示富文本的缩略内容 业务中有一个一览列表,显示某个对象的一览信息.列表的其中一列用来显示对象的内容的缩略显示,该内容是含有各种html标签的富文本内容.开始决定不做处理直接显示,但看到一个一个 ...

  3. kind富文本编辑器_在项目中集成富文本编辑器

    前   言 现在学程序的都离不开 Markdown 语法了吧,Markdown 已经成为典型的转换为HTML的非正式规范和参考实现,现在市场上也出现了许多Markdown实现,在基本语法之上额外增加了 ...

  4. Vue项目中tinymce富文本的安装以及配置

    Vue项目中tinymce富文本的安装以及配置 对于目前网上存在的许多富文本插件中,个人还是觉得tinymce相对比较强大一些.在使用配置的过程中,可能会出现配置不完全,导致使用不了的情况,下面把我个 ...

  5. 手机直播app制作时怎样在iOS中实现富文本

    我们在观看直播时,经常会看到有的主播房间名字下面带有话题小标签,比如#搞笑的一天##悲伤的瞬间##双十一买了点啥#等,虽然看起来是很小的一个功能,但是在进行手机直播app制作时,在iOS中通过富文本的 ...

  6. wangeditor ajax,laravel 中 wangEditor 富文本编辑器使用指南

    在本课程中,老师使用的富文本编辑器是 2.0 的版本,且输入区域使用的 textarea,但是在新的 3.0 版本中(新版本富文本编辑器只需要引用一个js文件即可),开发者不建议使用 textarea ...

  7. 在jango中添加富文本

    在jango中添加富文本: 大家都知道,大多数社交软件都可以编辑长文本,比如微博,QQ空间说说,微信朋友圈等,但是这些功能都是非富文本,因为他们的功能只能是文字,文字中也不能插图,只能最后再配图,所以 ...

  8. 浏览器中插入富文本编辑器

    常用的富文本编辑器有CKEditor.UEEditor.TinyEditor.KindEditor等.以下以kindeditor编辑器的使用为例. 1.官网下载KindEditor编辑器http:// ...

  9. TP5.1框架中百度富文本编辑器UEditor的使用

    在实际项目开发中最常使用到的工具之一就是富文本编辑器,使用富文本编辑器可以实现所见即所得的效果,且所有富文本编辑器里的内容(包括图片,视频,音乐等文件)全部可以带格式的存入数据库中且只需占用一个字段. ...

最新文章

  1. matlab显示服务器出现意外,Matlab 读取excel文件提示服务器出现意外情况或无法读取问题解决...
  2. 日记 [2008年03月26日]
  3. linux搭建--centos使用qemu-kvm,libvirt搭建虚拟机,并搭建libvmi来虚拟机自省(四)
  4. 认证概述散列函数数字签名
  5. SpringBoot 2.0 教程实战 MySQL 读写分离
  6. VC ado连接数据库
  7. 【Java面试题】40 你所知道的集合类都有哪些?主要方法?
  8. c语言 牛逼代码,有c语言牛逼的神人吗
  9. 【MapGIS精品教程】002:GDB本地数据库的使用
  10. insist用法扫描
  11. android dialog edittext 弹出软件盘,http://gogo.com-官方网站
  12. “onkeyup”=按键抬起触发,“onafterpaste”=粘贴之后触发
  13. windows下安装mathtype公式编辑器记录
  14. 数据模型及E-R模型
  15. 计算机网络(第7版) - 第七章 网络安全 - 习题
  16. 快手+中科大 | 全曝光推荐数据集KuaiRec 2.0版本
  17. 浅谈下载access数据库的攻与防
  18. 3dsmax 放样 操作
  19. 我眼中的微软Azure:Microsoft Azure
  20. 博客鼠标特效代码|鼠标特效代码

热门文章

  1. java 运行时类型_Java基础之RTTI 运行时类型识别
  2. linux nginx安启动_linux下nginx编译安装启动
  3. OBJ可视化——UV还原(修正)
  4. 如果硬盘不显示可以这么处理
  5. context-param和init-param的区别
  6. Android studio打开之后 cannot load project: java.lang.NUllpointerException
  7. 起一卦,还是那个破事。还是大凶。
  8. [翻译] Fast Image Cache
  9. 在Visual Studio上开发Node.js程序
  10. 获取网页中选中的文字