观摩一段简单粗暴的 vue 代码

2020-09-29 23:42:59 +08:00
 px920906

是一个 vue 的 updated 生命周期钩子:

  updated () {
    let tx = document.getElementsByClassName('textContent');
    for (let jj = 0; jj < tx.length; jj++) {
      while (tx[jj].offsetHeight < tx[jj].scrollHeight) {
        let ss = tx[jj].innerText;
        tx[jj].innerText = ss.substr(0, ss.length - 4);
        tx[jj].innerText += '...';
      }
    }
  }

页面是一个展示作品的页面,估计是设计要求作品简介的文字所占高度不超过一定值,超出部分裁掉用三个点代替。 作者的做法是等 vue 拿到数据并重新渲染 dom 之后把页面上所有.textContent 元素里的文字逐字删到所占高度刚好不超过元素高度(.textContent 高度固定)。作品有多条,再加上其他数据更新导致的重新渲染,这段代码会执行多次。

可能他 /她在开发和测试过程中没遇到文字很多的情况,现在我们遇到了一个两万字的数据,导致每次刷新页面至少需要 2 分钟,期间页面处于假死状态。用 chrome 性能面板录制了一下,耗时 4 分多钟,上个截图大伙感受一下:

设置 innerText 本身就是会导致强制同步布局的耗时操作,再循环两万次……

不过光指出问题不够,怎么解决?

我自己还真想不出好办法……不过首先会把这段逻辑放在获取作品数据完成后的一个 nextTick 里,而不是 updated 钩子里。另一个是获取到数据后直接限制文字长度为固定值,但不好保证最后行数以及文字末尾在行末,肯定过不了设计的关。或者,两者结合,先限制为一个尽量短但足够的长度,再执行上面的逻辑。

最后查到了-webkit-line-clamp这个 css 属性,感觉不考虑 IE 的话,就是它了。

大家有什么好的方案?

5965 次点击
所在节点    程序员
49 条回复
weixiangzhe
2020-09-30 15:41:04 +08:00
省略号用不了,可以用个 after 做个渐变的蒙层 很多公司这么整
lixuda
2020-09-30 15:50:13 +08:00
@f056917 如果是 flex 布局,怎么写?
tony1890
2020-09-30 15:54:31 +08:00
1. css 单行或多行
2. 超过隐藏,加一个省略号覆盖
3. 用 canvas 绘制文字,用 measureText 测绘,然后自己排版

真心不喜欢这些需求,直接不许换行多好。
pigzzz
2020-09-30 16:18:27 +08:00
css 啊,兄弟,这是基础
f056917
2020-09-30 16:27:06 +08:00
@lixuda 在 flex 元素下面再建个子元素
wangxiaoaer
2020-09-30 16:36:57 +08:00
@NullData 同意,如果必须通过计算字符个数,那么无脑遍历显然效率效率太低,二分法可以很大程度加快速度。甚至设置不同的区间用采用不同的分法。
zouri
2020-09-30 17:23:02 +08:00
这段代码我愿称之为 "什么这个特性那个特性,我就一把循环,搞不定就再上一层" 之术
iyangyuan
2020-09-30 22:33:17 +08:00
实在不行高度写死,用 absolute right 0 bottom 0 做一个假的...也比这强吧
dd0754
2020-10-01 09:00:25 +08:00
这不是前端写的吧,这种情况前端一般用 css

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/711713

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX