React中如何将contentEditable div选中文本替换为指定span元素
实现方案
你可以直接用浏览器原生Selection API完成选中文本包裹span的需求,完整实现如下:
import { useState, useRef } from 'react'; const EditableContent = () => { const [html, setHtml] = useState("<p>Hello World!</p>"); // 绑定可编辑div的ref,用于校验选中范围是否在容器内 const editableRef = useRef(null); const onClickHandler = () => { const selection = window.getSelection(); // 无选中内容直接返回 if (!selection || selection.rangeCount === 0) return; const range = selection.getRangeAt(0); const selectedText = range.toString().trim(); if (!selectedText) return; // 仅处理可编辑div内部的选中内容 if (!editableRef.current.contains(range.commonAncestorContainer)) return; const boldSpan = document.createElement('span'); boldSpan.className = 'text-bold'; // 包裹选中内容 range.surroundContents(boldSpan); // 同步最新HTML到state setHtml(editableRef.current.innerHTML); // 清空选中状态 selection.removeAllRanges(); }; return ( <> <div ref={editableRef} contentEditable="true" dangerouslySetInnerHTML={{ __html: html }} /> <button onClick={onClickHandler}>Bold</button> </> ) } export default EditableContent;
补充说明
- 如果需要支持跨标签选中的场景(比如选中内容同时属于多个嵌套标签),可以把
range.surroundContents(boldSpan)替换为以下兼容逻辑:const contentFragment = range.extractContents(); boldSpan.appendChild(contentFragment); range.insertNode(boldSpan); - 上述实现会自动同步最新的HTML内容到state的
html变量,符合你需要更新状态的要求。
内容的提问来源于stack exchange,提问作者BlackMath
相关产品推荐
相关产品推荐

