react-native-pell-rich-editor v1.9.0中H1/H2与列表组合使用时文本尺寸无限增大的问题
react-native-pell-rich-editor v1.9.0中H1/H2与列表组合使用时文本尺寸无限增大的问题
我之前也踩过这个一模一样的坑!这个问题的核心原因是:编辑器在列表项(<li>)内切换H1/H2样式时,没有正确检测已存在的标题标签,而是重复嵌套H1/H2标签——比如第一次切换是<li><h1>文本</h1></li>,第二次切换就变成了<li><h1><h1>文本</h1></h1></li>,浏览器会继承每层标题的字体大小,自然就无限增大了。
下面是我亲测有效的几种解决方案,按推荐优先级排序:
方案1:从逻辑层面阻止重复嵌套(最推荐)
直接修改工具栏按钮的点击逻辑,先检查当前选中内容的标签状态,避免重复套娃:
- 自定义H1/H2工具栏按钮,替换默认的内置动作:
<RichToolbar editor={richText} // 用自定义按钮代替默认的heading1/heading2 actions={[ 'customHeading1', 'customHeading2', actions.insertBulletsList, actions.insertOrderedList, ]} // 自定义按钮的显示样式 iconMap={{ customHeading1: () => <Text style={{fontSize:24, fontWeight:'bold', padding: 4}}>H1</Text>, customHeading2: () => <Text style={{fontSize:20, fontWeight:'bold', padding: 4}}>H2</Text>, }} // 自定义按钮点击逻辑 onPressToolbarAction={(action) => { if (action === 'customHeading1' || action === 'customHeading2') { const targetTag = action === 'customHeading1' ? 'H1' : 'H2'; // 先获取当前选中的元素,判断是否已经是目标标题 richText.current?.getSelectedElement().then((element) => { const isAlreadyTarget = element.tagName === targetTag || (element.parentElement?.tagName === 'LI' && element.tagName === targetTag); if (isAlreadyTarget) { // 如果已经是目标标题,切换回普通段落 richText.current?.execCommand('formatBlock', false, 'P'); } else { // 否则应用目标标题样式 richText.current?.execCommand('formatBlock', false, targetTag); } }); } else { // 列表类的默认动作直接执行 richText.current?.execCommand(action, false, null); } }} />
这个逻辑从根源上杜绝了重复嵌套的可能,是最彻底的解决方式。
方案2:注入CSS强制固定样式(最快应急)
你之前尝试的CSS思路是对的,但问题是没有把样式正确注入到编辑器的WebView渲染环境里。直接写全局CSS无效,需要通过编辑器的属性传入:
// 先定义要注入的自定义样式 const customEditorStyles = ` /* 强制固定列表内H1/H2的字体大小,不受嵌套影响 */ li h1 { font-size: 2em !important; font-weight: bold; margin: 0.67em 0; } li h2 { font-size: 1.5em !important; font-weight: bold; margin: 0.75em 0; } /* 或者如果你想让列表内标题和列表项字体逻辑一致,用inherit */ /* li { font-size: 16px; } li h1, li h2 { font-size: inherit !important; } */ `; // 在RichEditor组件中传入样式 <RichEditor ref={richText} editorStyle={customEditorStyles} // 其他属性... />
这种方法直接从渲染层强制固定字体大小,哪怕标签嵌套了,样式也会强制覆盖生效,适合赶工期时快速救场。
方案3:清理提交内容的冗余标签(最后兜底)
如果以上两种方法都暂时没法用,可以在获取编辑器内容时,手动用正则清理重复嵌套的标题标签:
const getCleanedContent = async () => { let rawContent = await richText.current?.getContent(); // 替换掉所有嵌套的H1/H2标签 rawContent = rawContent.replace(/<h([12])>(<h\1>.*?<\/h\1>)<\/h\1>/g, '<h$1>$2</h$1>'); // 额外清理列表内的嵌套 rawContent = rawContent.replace(/<li>.*?<h([12])>(<h\1>.*?<\/h\1>)<\/h\1>.*?<\/li>/g, '<li><h$1>$2</h$1></li>'); return rawContent; };
这个方法适合在提交内容前做最后处理,确保存储的内容没有冗余标签,避免后续渲染出问题。
这个问题是react-native-pell-rich-editor 1.9.0版本的一个已知小bug,以上三种方法都能有效解决,你可以根据自己的项目情况选择~




