fix(练习): 修复输入法组合期间焦点跳转导致字母分散问题
- 组合输入期间禁止useEffect自动聚焦到下一个空输入框 - onCompositionEnd直接传入index和value,不再扫描数组查找 - 确保拼音字母留在同一输入框,确认后正确分散成中文 via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
@@ -11,8 +11,8 @@ interface InputAreaProps {
|
||||
inputLocked: boolean
|
||||
lastErrorTimestamp: number | null
|
||||
onInputChange: (newInput: string[]) => void
|
||||
onCompositionStart: () => void
|
||||
onCompositionEnd: () => void
|
||||
onCompositionStart: (index: number) => void
|
||||
onCompositionEnd: (index: number, value: string) => void
|
||||
onPaste: (e: React.ClipboardEvent) => void
|
||||
}
|
||||
|
||||
@@ -31,11 +31,12 @@ export function InputArea({
|
||||
|
||||
// 自动聚焦到第一个空输入框
|
||||
useEffect(() => {
|
||||
if (isComposing || inputLocked) return
|
||||
const firstEmptyIndex = userInput.findIndex((char) => !char)
|
||||
if (firstEmptyIndex !== -1 && inputRefs.current[firstEmptyIndex]) {
|
||||
inputRefs.current[firstEmptyIndex]?.focus()
|
||||
}
|
||||
}, [userInput])
|
||||
}, [userInput, isComposing, inputLocked])
|
||||
|
||||
const handleCharInput = (
|
||||
index: number,
|
||||
@@ -137,8 +138,10 @@ export function InputArea({
|
||||
value={char}
|
||||
onChange={(e) => handleCharInput(index, e)}
|
||||
onKeyDown={(e) => handleKeyDown(index, e)}
|
||||
onCompositionStart={onCompositionStart}
|
||||
onCompositionEnd={onCompositionEnd}
|
||||
onCompositionStart={() => onCompositionStart(index)}
|
||||
onCompositionEnd={(e) =>
|
||||
onCompositionEnd(index, e.currentTarget.value)
|
||||
}
|
||||
onPaste={onPaste}
|
||||
disabled={inputLocked}
|
||||
className={clsx(
|
||||
|
||||
@@ -207,39 +207,41 @@ export default function ProcessPracticePage() {
|
||||
)
|
||||
|
||||
// 输入法状态管理
|
||||
const handleCompositionStart = useCallback(() => {
|
||||
const handleCompositionStart = useCallback((_index: number) => {
|
||||
isComposingRef.current = true
|
||||
setIsComposing(true)
|
||||
}, [])
|
||||
|
||||
const handleCompositionEnd = useCallback(() => {
|
||||
const handleCompositionEnd = useCallback(
|
||||
(index: number, value: string) => {
|
||||
isComposingRef.current = false
|
||||
setIsComposing(false)
|
||||
// 输入法确认后,需要将当前输入框中的所有字符分散到后续输入框
|
||||
requestAnimationFrame(() => {
|
||||
const currentInput = latestInputRef.current
|
||||
// 找到第一个有内容且长度>1的输入框(输入法组合的结果)
|
||||
const composedIndex = currentInput.findIndex((char) => char.length > 1)
|
||||
|
||||
if (composedIndex !== -1) {
|
||||
const composedText = currentInput[composedIndex]
|
||||
const chars = composedText.split('')
|
||||
const composedText = value
|
||||
const newInput = [...currentInput]
|
||||
|
||||
// 将组合的字符分散到后续输入框
|
||||
for (let i = 0; i < chars.length && composedIndex + i < newInput.length; i++) {
|
||||
newInput[composedIndex + i] = chars[i]
|
||||
if (composedText) {
|
||||
const chars = composedText.split('')
|
||||
for (
|
||||
let i = 0;
|
||||
i < chars.length && index + i < newInput.length;
|
||||
i++
|
||||
) {
|
||||
newInput[index + i] = chars[i]
|
||||
}
|
||||
} else {
|
||||
newInput[index] = ''
|
||||
}
|
||||
|
||||
latestInputRef.current = newInput
|
||||
setUserInput(newInput)
|
||||
validateInput(newInput)
|
||||
} else {
|
||||
// 没有多字符组合,直接验证当前输入
|
||||
validateInput(currentInput)
|
||||
}
|
||||
})
|
||||
}, [validateInput])
|
||||
},
|
||||
[validateInput]
|
||||
)
|
||||
|
||||
// 批量粘贴处理
|
||||
const handlePaste = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user