You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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:从逻辑层面阻止重复嵌套(最推荐)

直接修改工具栏按钮的点击逻辑,先检查当前选中内容的标签状态,避免重复套娃:

  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,以上三种方法都能有效解决,你可以根据自己的项目情况选择~

火山引擎 最新活动