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

使用contentEditable与onInput时,输入文本后光标跳至开头如何解决?

解决contentEditable输入后光标跳转到开头的问题

问题根源是:当你在onInput中更新状态(比如widget.alterations.title),组件会重新渲染,contentEditable的div被重新生成,光标位置因此重置到开头。要解决这个问题,需要先保存光标位置,再更新状态,最后在组件重新渲染后恢复光标位置。

具体实现步骤

  • 用useRef获取contentEditable元素的引用
  • 在onInput事件触发时,先记录当前的光标/选中范围
  • 更新状态后,通过useEffect监听状态变化,恢复之前保存的光标位置

修改后的代码示例

import { useState, useEffect, useRef } from 'react';

const YourComponent = ({ widget }) => {
  // 本地维护修改后的状态,避免直接修改props
  const [alterations, setAlterations] = useState(widget.alterations);
  // 保存光标选中范围
  const [selectionRange, setSelectionRange] = useState(null);
  // 获取contentEditable元素的引用
  const editableRef = useRef(null);

  const alter = (e) => {
    // 记录当前光标/选中范围
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      // 克隆Range对象,避免原Range在DOM更新后失效
      setSelectionRange(selection.getRangeAt(0).cloneRange());
    }
    // 获取编辑后的文本内容
    const newTitle = e.currentTarget.textContent;
    // 更新状态
    setAlterations(prev => ({ ...prev, title: newTitle }));
  };

  // 状态更新后恢复光标位置
  useEffect(() => {
    if (selectionRange && editableRef.current) {
      const selection = window.getSelection();
      selection.removeAllRanges();
      selection.addRange(selectionRange);
      // 重置选中范围,避免重复触发恢复逻辑
      setSelectionRange(null);
    }
  }, [alterations.title, selectionRange]);

  return (
    <div
      ref={editableRef}
      contentEditable
      data-which="title"
      onClick={e => {
        e.stopPropagation();
        e.preventDefault();
      }}
      onInput={alter}
      className={styles.widgetSignalTitleText}
    >
      {alterations.title}
    </div>
  );
};

关键说明

  • 必须克隆Range对象:原Range对象会在DOM重新渲染后与旧DOM节点绑定,克隆后才能关联到新渲染的节点
  • 本地维护状态:避免直接修改传入的widget.alterations props,确保状态更新触发组件重新渲染的逻辑正确
  • 恢复光标后重置selectionRange:防止useEffect重复执行恢复逻辑,导致光标异常

内容的提问来源于stack exchange,提问作者codingrohtak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:51:12