You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NEXT.js自定义富文本编辑器问题:选中文本加粗功能实现异常求助

解决Next.js富文本编辑器的加粗功能问题及SunEditor使用经验

一、解决“点击两次才获取选区”的问题

问题出在点击加粗按钮时,浏览器会自动把焦点从编辑器转移到按钮上,导致选区被清空。解决思路是在按钮的mousedown事件里阻止默认行为,提前保存选区:

import { useState } from 'react';

export default function RichTextEditor() {
  const [content, setContent] = useState('<p>编辑你的内容...</p>');
  let selectionRange = null;

  // 保存当前选区
  const saveSelection = () => {
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      selectionRange = selection.getRangeAt(0);
    }
  };

  const handleBold = () => {
    const editor = document.getElementById('rich-editor');
    editor.focus();
    // 恢复之前保存的选区
    if (selectionRange) {
      const selection = window.getSelection();
      selection.removeAllRanges();
      selection.addRange(selectionRange);
    }

    // 执行加粗命令
    document.execCommand('bold', false, null);
    // 更新编辑器内容状态
    setContent(editor.innerHTML);
  };

  return (
    <div>
      <button onMouseDown={saveSelection} onClick={handleBold}>加粗</button>
      <div
        id="rich-editor"
        contentEditable
        dangerouslySetInnerHTML={{ __html: content }}
        style={{ border: '1px solid #ccc', padding: '10px', minHeight: '200px' }}
      />
    </div>
  );
}

二、手动将选中文本转为标签(替代execCommand)

如果不想用已废弃的execCommand,可以手动操作DOM完成标签包裹:

const handleBoldManual = () => {
  const editor = document.getElementById('rich-editor');
  editor.focus();
  const selection = window.getSelection();
  
  if (!selection.toString()) return; // 无选中内容直接返回

  const range = selection.getRangeAt(0);
  const boldTag = document.createElement('b');
  // 将选中内容包裹进<b>标签
  range.surroundContents(boldTag);

  // 更新内容状态
  setContent(editor.innerHTML);
};

注意:如果选区内包含多个独立DOM节点,surroundContents可能报错,需要额外处理节点拆分逻辑,简单编辑场景下上述代码足够使用。

三、SunEditor在Next.js中的使用经验

  1. 基础集成步骤
    先安装依赖:npm install suneditor suneditor-react
    在Next.js组件中动态导入(避免SSR报错):

    import dynamic from 'next/dynamic';
    const SunEditor = dynamic(() => import('suneditor-react'), { ssr: false });
    import 'suneditor/dist/css/suneditor.min.css';
    
    export default function SunEditorDemo() {
      const handleChange = (content) => {
        console.log('编辑后内容:', content);
      };
    
      return (
        <SunEditor
          onChange={handleChange}
          setOptions={{
            toolbar: ['bold', 'font', 'fontSize', 'paragraph'], // 自定义需要的工具栏按钮
            height: 300,
          }}
        />
      );
    }
    
  2. 核心优势

    • 开箱即用,无需自己从零实现段落、字体样式等基础功能,节省开发时间
    • 工具栏可完全自定义,适配促销内容编辑的需求
    • 内置XSS防护,处理用户输入更安全
    • 输出HTML结构简洁,方便后续直接渲染到前端页面
  3. 常见问题处理

    • SSR报错:必须用dynamic导入并关闭SSR,因为SunEditor依赖浏览器DOM环境
    • 自定义格式:通过setOptions的customToolbar添加自定义按钮,或在onChange钩子中对输出内容做二次处理

内容的提问来源于stack exchange,提问作者XAZG Неизвестный

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:30:49