React contentEditable组件如何避免每次输入都触发onSelect事件
解决方案
问题原因
contentEditable元素的onSelect事件触发规则和普通输入框不同,只要元素内的选区发生变化就会触发(包括点击定位光标、输入内容后光标重置、调整光标位置等场景),并非只有选中有效文本时才触发,因此需要在回调中增加判断逻辑过滤无效触发。
实现方案
核心逻辑是在onSelect触发时,判断当前是否存在选中的有效文本,且选区位于当前编辑器内部,满足条件才执行目标操作:
- 使用
useRef获取contentEditable元素的DOM实例,用于选区范围校验 - 在
onSelect回调中通过window.getSelection()获取当前选区 - 校验选区是否在编辑器内部、且选中文本长度大于0,通过则执行自定义逻辑
修改后的完整代码
import { useRef } from 'react'; function EditorBody(props) { const editorRef = useRef(null); const handleSelect = () => { const selection = window.getSelection(); // 没有选区、选区内无文本直接返回 if (!selection || selection.toString().length === 0) return; // 校验选区是否在当前编辑器内部 const range = selection.getRangeAt(0); if (!editorRef.current?.contains(range.commonAncestorContainer)) return; // 这里写你要执行的自定义逻辑 window.alert("You've selected a text"); }; return ( <div className="editor-body"> <div ref={editorRef} className="text-section" contentEditable role="textbox" placeholder="Text goes here ..." onSelect={handleSelect} ></div> </div> ); } export default EditorBody;
补充说明
如果需要进一步过滤边缘场景,可以额外判断selection.isCollapsed属性,该值为true时表示选区是折叠状态(即只有光标没有选中文本),可以直接过滤。
内容的提问来源于stack exchange,提问作者noiseymur
相关产品推荐
相关产品推荐

