react-rnd内嵌textarea选中文本移出组件后选区错乱如何解决?
React Rnd 嵌套textarea文本选区异常解决方案
根因说明
该问题由react-rnd拖拽事件机制和textarea原生文本选区逻辑冲突导致:
- react-rnd默认监听组件全范围的
mousedown、mousemove、mouseup事件实现拖拽能力 - 当在textarea内选中文本并拖动鼠标超出组件边界时,react-rnd的拖拽逻辑会被触发,打断浏览器原生的文本选区计算,最终出现选区异常跳转的情况
- textarea放在可拖拽组件外不会触发问题,是因为其不在react-rnd的事件监听范围内,不会被抢占事件执行权
解决方案
方案1:指定专属拖拽触发区域(推荐)
给react-rnd设置拖拽手柄,仅点击指定的手柄区域才触发拖拽,textarea区域完全不参与拖拽逻辑,不会影响原生文本操作:
import { Rnd } from "react-rnd"; export default function App() { return ( <div className="App"> <Rnd default={{ x: 100, y: 100, width: 300, height: 200, }} // 仅带drag-handle类名的元素可触发拖拽 dragHandleClassName="drag-handle" > {/* 专属拖拽手柄 */} <div className="drag-handle" style={{ padding: '6px 8px', background: '#f0f0f0', cursor: 'move' }} > 拖拽此处移动组件 </div> <textarea style={{ width: '100%', height: 'calc(100% - 36px)', userSelect: 'text', border: '1px solid #d9d9d9' }} defaultValue="hello world" /> </Rnd> </div> ); }
方案2:禁止textarea区域触发拖拽
如果需要保留点击组件任意空白区域拖拽的能力,可在react-rnd的拖拽启动事件中加判断,触发源为textarea时直接阻止拖拽启动:
import { Rnd } from "react-rnd"; export default function App() { return ( <div className="App"> <Rnd default={{ x: 100, y: 100, width: 300, height: 200, }} onDragStart={(e) => { // 触发源为textarea内部时,阻止拖拽启动 if (e.target.closest('textarea')) { return false; } }} > <textarea style={{ width: '100%', height: '100%', userSelect: 'text', border: '1px solid #d9d9d9' }} defaultValue="hello world" /> </Rnd> </div> ); }
注意事项
需给textarea显式设置userSelect: text样式,避免react-rnd默认的userSelect: none样式继承,影响文本选中能力。
内容的提问来源于stack exchange,提问作者sundar sundar
相关产品推荐
相关产品推荐

