2.2 KiB
2.2 KiB
第一章:为什么算文字高度也会慢
1.1 字符数不能直接决定高度
假设一段话放在宽 320px 的聊天气泡中。它会占几行,至少取决于文字内容、字体、字号、可用宽度、字间距和换行规则。
同样长度的 iiii 和 WWWW 宽度可能差很多。中文通常能在许多字之间断行,英文更常在空格处换行;标点又有自己的限制。所以“字符数乘平均字宽”只能估计,无法可靠地预测真正的行数。
传统方案是让浏览器先排一遍,再读取结果:
element.textContent = text
element.style.width = '320px'
const height = element.getBoundingClientRect().height
写入文字或宽度后,之前的排版结果可能失效。此时立刻读取几何信息,浏览器必须先保证这个结果是最新的;如果有待处理的样式或布局工作,就可能同步完成这些工作。
这就是这里关心的“回流”或“布局”:确定元素的尺寸与位置。一次几何读取不一定总触发昂贵回流,关键在于读取时是否存在需要更新的布局。
1.2 写与读交替,会放大成本
for (const row of rows) {
row.element.style.width = width + 'px'
heights.push(row.element.getBoundingClientRect().height)
}
这个循环可能不断要求浏览器“写一点、立即排好、读出来”。把写操作与读操作分批,通常能改善它。但虚拟列表还有另一个问题:大多数行根本没有挂载,无法直接读取那些行的 DOM 高度。
Pretext 的切入点是:如果能在应用代码中算出文本行数,就能在创建那些 DOM 之前知道高度。 浏览器最终仍然负责把字画出来。
1.3 区分布局和绘制
把一段文字显示到屏幕上,可以粗略拆成:
文字与样式 → 确定字形和宽度 → 决定换行与位置 → 绘制文字
Pretext 借助 Canvas 的字体测量,自己完成一部分换行与布局计算。它不是一个自动让任意页面绘制都变快的开关,也不承担完整的浏览器 CSS 排版。
本章检查:如果宽度变化,文字本身的字体宽度一定要重新测量吗?通常不需要。变的是“每行能装多少”,这就是下一章的设计基础。