为什么Word.Range的expandTo方法会修改Word Online的撤销栈?
问题原因
这个现象是网页版Word JS API的已知Bug,本地版Word(Win32、Mac客户端)暂未复现该问题。
虽然你没有显式修改激活选区,但是网页版当前的expandTo方法底层实现存在缺陷:方法执行时会隐式创建一个临时选区实例用于范围计算,这个临时操作被错误地纳入了撤销栈的追踪范围,最终导致撤销栈多了一条无效条目。
规避方案
目前有两种稳定的规避方案可以彻底解决撤销栈异常的问题:
- 替换
expandTo实现,手动构造合并范围
不需要调用原生expandTo方法,通过读取两个范围的起止位置自行拼接新范围,完全绕开有缺陷的API:
这个方案不会触发任何撤销栈变更,性能和原生Word.run(async (context): Promise<void> => { const firstRange = context.document.body.paragraphs.getFirst().getRange('Start') const secondRange = context.document.body.paragraphs.getLast().getRange('End') // 加载两个范围的起止位置和所属body对象 firstRange.load(['start', 'end', 'parentBody']) secondRange.load(['start', 'end']) await context.sync() // 取最小起始位置、最大结束位置构造新范围 const mergedStart = Math.min(firstRange.start, secondRange.start) const mergedEnd = Math.max(firstRange.end, secondRange.end) const expanded = firstRange.parentBody.getRange(mergedStart, mergedEnd).load('text') await context.sync() console.log(expanded.text) })expandTo基本一致。 - 开启事务批处理(适合多操作场景)
如果你需要同时执行多个范围操作,可以将所有操作包裹在一个撤销事务中,完成后只生成一条撤销条目,也能规避这个问题:
调用context.document.startUndoScope("自定义操作名")开启事务,所有操作完成后调用context.document.endUndoScope()提交事务,中间所有操作(包括expandTo产生的临时撤销条目)都会被合并为单条,用户只需要按一次ctrl+z就能撤销全部操作。
官方修复进度
该Bug已经被微软Office JS团队确认,目前在预览版通道中已经完成修复,预计2024年第四季度推送至网页版正式环境。
内容的提问来源于stack exchange,提问作者Theo
相关产品推荐
相关产品推荐

