React Quill布局变动时formatText设置的高亮格式丢失如何解决
根本触发原因
- 核心原因是你通过
formatText()添加的高亮样式没有被注册为Quill认可的合法格式,Quill每次触发内容清洗流程时,会自动剔除所有不在自身格式白名单内的属性,直接从delta数据源层面删除对应格式标记,这也是你调用getContents()能看到格式属性消失的本质原因,不是视图层样式丢失,是数据源已经被清洗。 - 你遇到的两个触发场景,本质都是触发了Quill的自动内容清洗流程:
- 点击汉堡菜单折叠MUI侧边栏时,页面整体布局发生重排,react-quill感知到父容器尺寸变化后会触发编辑器重绘,同步执行一次全量delta合法性校验
- 移动端收起虚拟键盘时,视口尺寸变化、编辑器失焦,同样会触发Quill的失焦校验、视图重排逻辑
- 如果你调用
formatText()时是直接给文本节点加内联样式、临时class,没有绑定到Quill的Parchment格式定义上,清洗逻辑会直接判定这类属性为非法冗余内容,直接清除。
持久保留格式的解决方案
按以下优先级落地即可彻底解决该问题:
- 先将高亮格式正式注册到Quill全局,作为合法内联格式存在
参考代码实现:
注册完成后,搜索匹配到文本时不要直接设置background样式,改用注册好的格式调用API:import Quill from 'quill'; const Parchment = Quill.import('parchment'); // 定义搜索高亮专属格式 class SearchHighlight extends Parchment.Attributor.Class { add(node) { node.classList.add('search-match-highlight'); return true; } remove(node) { node.classList.remove('search-match-highlight'); } value(node) { return node.classList.contains('search-match-highlight'); } } // 注册格式,第二个参数true代表覆盖可能存在的同名格式 Quill.register( new SearchHighlight('searchHighlight', 'search-match-highlight', { scope: Parchment.Scope.INLINE }), true );// 错误写法:直接设置内联样式,未注册的属性会被清洗 // quill.formatText(matchIndex, matchLength, { background: '#fff176' }); // 正确写法:调用已注册的合法格式 quill.formatText(matchIndex, matchLength, 'searchHighlight', true, 'api'); - 规避不必要的Quill重渲染触发
- 不要将编辑器的delta/value值绑定到随侧边栏折叠、视口尺寸变化更新的state上,避免父组件重渲染带动react-quill销毁重建
- 给编辑器外层容器设置最小高度、宽度过渡规则,折叠侧边栏时让容器尺寸平滑变化,减少Quill触发强制重排校验的概率
- 移动端场景下不要在编辑器
blur事件里主动同步value到state、调用setContents更新内容,避免触发内容覆盖
- 兜底兼容处理
在侧边栏折叠、虚拟键盘收起这类会触发布局重排的交互触发前,先通过getContents()存一份当前编辑器的delta快照,等交互完成、过渡动画结束(通常延迟300ms即可),对比当前编辑器文本内容和快照文本内容,如果文本完全一致但格式存在缺失,就调用setContents(snapshot, 'silent')静默恢复内容,不会触发额外的内容变更事件。
内容的提问来源于stack exchange,提问作者rog8gm
相关产品推荐
相关产品推荐

