虚拟列表中的选区操作
在某些长列表场景中,为了优化渲染性能,一般会采用虚拟列表,虚拟列表会将超过一定可视范围的 DOM 节点移除通过 padding 或者绝对定位去填充高度。
在被移除的节点上,是无法应用选区的。假设现在有场景我们需要一个长列表中的复制文本的需求,为了性能又要兼顾使用虚拟列表。此时我们使用原生选区滚动超过一定范围之后,之前的选区就丢失了,导致复制的内容不完全。
下面是一个简单的例子,你可以亲自尝试一下。
Component Loading...
原生选区行不通,我们要学会变通。类似 VSCode 在类的编辑器都是采用的虚拟选区,通过监听选区操作再结合一套自己的选区管理实现去选区的把控。当然我们的需求并没有这么复杂的。
我们可以通过监听选区的开始,记录开始位置的数据索引和选中的文本在段落中的偏移。然后在 onCopy
事件时,再次获取当前的选区的末尾节点在数据中的索引和末尾的文本的偏移。根据两次的索引找到数据中的切片,根据数据再去拼接出我们需要复制出的内容。
Excalidraw Loading...
下面这个例子你可以亲自尝试一下。
Component Loading...
当然上面的方式,只适用于内容简单的场景,并且复制出的内容只能是纯文本。并且原本选区渲染在节点丢失之后会出现问题,你或许需要手动实现一套虚拟选区,但是虚拟选区对于 VSCode 这种等宽且高度一致的场景下才好实现。这里只是抛砖引玉。
Demo: