React富文本编辑器:contentEditable光标跳转至起始位置问题排查
解决React富文本编辑器光标跳转问题(保留HTML清理函数)
问题核心:每次通过dangerouslySetInnerHTML重新渲染内容时,React会完全替换contentEditable元素的内部HTML,导致输入光标被重置到起始位置。要保留freeAllAttributeHTML的同时解决这个问题,需要手动管理光标位置。
解决步骤
- 保存光标位置:在更新内容状态前,记录当前光标在编辑区域的选区范围
- 恢复光标位置:内容更新完成、组件重新渲染后,将光标恢复到之前记录的位置
- 确保HTML结构一致性:
freeAllAttributeHTML清理时尽量保持标签结构不变,避免因结构差异导致光标定位失效
修改后的完整代码
import React, { useState, useRef, useEffect } from 'react' function App() { const [content, setContent] = useState('') const editableRef = useRef(null) let cursorRange = null // 保存当前光标/选区位置 const saveCursorPosition = () => { const selection = window.getSelection() if (selection.rangeCount > 0) { cursorRange = selection.getRangeAt(0) } } // 恢复光标/选区位置 const restoreCursorPosition = () => { if (!cursorRange || !editableRef.current) return const selection = window.getSelection() selection.removeAllRanges() selection.addRange(cursorRange) } const freeAllAttributeHTML = (htmlString) => { let cleanedHtml = String(htmlString).replaceAll(/<div[^>]*>/g, '<div>'); cleanedHtml = cleanedHtml.replaceAll(/<p[^>]*>/g, '<p>'); cleanedHtml = cleanedHtml.replaceAll(/<span[^>]*>/g, '<span>'); cleanedHtml = cleanedHtml.replaceAll(/<button[^>]*>/g, '<button>'); cleanedHtml = cleanedHtml.replaceAll(/<a[^>]*>/g, '<a>'); cleanedHtml = cleanedHtml.replaceAll(/<svg[^>]*>/g, '<svg>'); cleanedHtml = cleanedHtml.replaceAll(/<img[^>]*>/g, ''); return cleanedHtml; } const handleContentChange = (e) => { // 更新前先保存光标位置 saveCursorPosition() const cleanedContent = freeAllAttributeHTML(e.target.innerHTML) setContent(cleanedContent) } // 内容更新后恢复光标 useEffect(() => { restoreCursorPosition() }, [content]) return ( <> <div> <strong>hello one</strong> <em> hello two</em> </div> <div ref={editableRef} className='editable' contentEditable={true} dangerouslySetInnerHTML={{ __html: content }} onInput={handleContentChange} /> </> ) } export default App
关键说明
editableRef:获取contentEditable元素的DOM引用,用于后续光标操作saveCursorPosition:利用window.getSelection()记录当前光标所在的Range对象useEffect:监听content状态变化,每次内容更新完成后调用restoreCursorPosition恢复光标- 注意:如果
freeAllAttributeHTML对HTML结构修改较大(比如删除了某些标签),可能导致光标无法准确定位,需要调整清理规则尽量保留原有标签层级
内容的提问来源于stack exchange,提问作者Mehedi Setu
相关产品推荐
相关产品推荐

