diff --git a/src/App.tsx b/src/App.tsx index 6c7ebb0..c7113c9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,8 +7,10 @@ import { getDemoServerInstance } from "./ot/server"; function Editor({ name }: { name: string }) { const clientRef = useRef(null); const [doc, setDoc] = useState(""); + const [inputValue, setInputValue] = useState(""); const prevDocRef = useRef(""); const [enableSync, setEnableSync] = useState(true); + const isComposingRef = useRef(false); // 初始化client和文档状态 useLayoutEffect(() => { @@ -18,6 +20,7 @@ function Editor({ name }: { name: string }) { const initialDoc = clientRef.current.document || ""; prevDocRef.current = initialDoc; setDoc(initialDoc); + setInputValue(initialDoc); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -35,9 +38,19 @@ function Editor({ name }: { name: string }) { return () => clearInterval(timer); }, []); - const handleChange = (e: React.ChangeEvent) => { + // 当doc变化时,同步到inputValue + useEffect(() => { + setInputValue(doc); + }, [doc]); + + const handleChange = (newValue: string) => { if (!clientRef.current) return; - const newValue = e.target.value; + // 立即更新inputValue,让输入框响应更快 + setInputValue(newValue); + // 如果正在输入CJK字符,不触发onChange逻辑 + if (isComposingRef.current) { + return; + } // 使用client当前文档状态作为旧值 const oldValue = clientRef.current.document || ""; if (newValue !== oldValue) { @@ -50,6 +63,16 @@ function Editor({ name }: { name: string }) { } }; + const handleCompositionStart = () => { + isComposingRef.current = true; + }; + + const handleCompositionEnd = (e: React.CompositionEvent) => { + isComposingRef.current = false; + // composition结束后,手动触发一次change处理 + handleChange(e.currentTarget.value); + }; + const handleToggleSync = () => { const newValue = !enableSync; setEnableSync(newValue); @@ -59,7 +82,9 @@ function Editor({ name }: { name: string }) { }; return ( -
+
同步到服务端
-