Expand document collections with Pretext tutorial and simplify library navigation
Verify and deploy Tabularium / verify-and-deploy (push) Successful in 5m47s
Verify and deploy Tabularium / verify-and-deploy (push) Successful in 5m47s
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# 第六章:为什么只求高度比拿到每行文字便宜
|
||||
|
||||
### 6.1 计算结果越详细,需要的工作越多
|
||||
|
||||
假设一个段落有 50 行。高度只需要一个行数;返回每行文字则还要确定范围、切字符串、拼接内容并创建结果对象。这些临时对象最终还需要垃圾回收。
|
||||
|
||||
因此选择 API 时应先问:调用者实际要什么?
|
||||
|
||||
| 需求 | 准备方式 | 布局 API |
|
||||
| --- | --- | --- |
|
||||
| 高度、行数 | `prepare()` | `layout()` |
|
||||
| 行数、最宽行 | `prepare()` | `measureLineStats()` |
|
||||
| 每行范围与宽度 | `prepare()` | `walkLineRanges()` |
|
||||
| 每行文字 | `prepareWithSegments()` | `layoutWithLines()` |
|
||||
| 逐行取文字,可按需停止 | `prepareWithSegments()` | `layoutNextLine()` |
|
||||
|
||||
普通 `prepare()` 的最终 handle 不保留分段字符串;准备过程中仍会使用文字,不能因此说它完全没有字符串处理。
|
||||
|
||||
### 6.2 范围与文字分开生成
|
||||
|
||||
一行可以先表示为:
|
||||
|
||||
```text
|
||||
从第几个 segment 的第几个字素开始
|
||||
到第几个 segment 的第几个字素结束
|
||||
这一行有多宽
|
||||
```
|
||||
|
||||
这是 range。需要显示那一行时,再把 range 变成实际字符串,这一步叫 materialize,即生成具体内容。
|
||||
|
||||
`walkLineRanges()` 不生成行字符串,但公共回调接收的 range 及其游标仍然会分配对象。它比“每行完整文字”做得少,也不应被描述成零分配。
|
||||
|
||||
[`line-text.ts`](https://github.com/chenglou/pretext/blob/0d102a5cd933611e86a7e60bda7b4baa5995c6b0/src/line-text.ts)还用 WeakMap 按 handle 缓存所需分段的字素结束位置。只有行边界切进一个分段内部、确实需要定位字素时,才会补上相关数据。
|
||||
|
||||
### 6.3 流式逐行适合什么情境
|
||||
|
||||
如果只显示前三行摘要,逐行 API 可以在取到所需行数时停止;如果每行可用宽度不同,也可以逐次传入不同宽度。
|
||||
|
||||
```js
|
||||
let cursor
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const line = layoutNextLine(preparedWithSegments, 320, cursor)
|
||||
if (!line) break
|
||||
console.log(line.text)
|
||||
cursor = line.end
|
||||
}
|
||||
```
|
||||
|
||||
这个片段假设已经导入 `layoutNextLine` 并准备好 `preparedWithSegments`。它演示逐行读取,不包含省略号处理。高度用途直接选 `layout()` 会更合适。
|
||||
|
||||
本章检查:虚拟列表只想知道 10,000 条消息各有多高,是否需要为每条创建所有行字符串?不需要。
|
||||
|
||||
Reference in New Issue
Block a user