Featured image of post React 解決中文輸入法

React 解決中文輸入法

今天在開發晶晶體產生器的時候,發現中文輸入總是有問題,這時候我想起以前看過 Hackmd 官方的一篇 blog,提到中文輸入法如果有問題,可能和組字事件有關。於是就開始研究。首先我將以下設定加入 textarea 裡觀察組字事件的行為

1
2
3
onCompositionStart={(e) => console.log('compositionStart', e.data)}
onCompositionEnd={(e) => console.log('compositionEnd', e.data)}
onCompositionUpdate={(e) => console.log('compositionUpdate', e.data)}

當我打「今天我想要吃蛋餅」的時候,console 長這樣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
compositionStart <empty string>
compositionUpdate ㄐ
compositionUpdate ㄐㄧ
compositionUpdate ㄐㄧㄣ
compositionUpdate 今
compositionUpdate 今ㄊ
compositionUpdate 今ㄊㄧ
compositionUpdate 今ㄊㄧㄢ
compositionUpdate 今天
compositionUpdate 今天ㄨ
compositionUpdate 今天ㄨㄛ
compositionUpdate 今天ㄒㄨㄛ
compositionUpdate 今天ㄒㄨ
compositionUpdate 今天ㄒ
compositionUpdate 今天
compositionUpdate 今天ㄨ
compositionUpdate 今天ㄨㄛ
compositionUpdate 今天我
compositionUpdate 今天我ㄒ
compositionUpdate 今天我ㄒㄧ
compositionUpdate 今天我ㄒㄧㄤ
compositionUpdate 今天我想
compositionUpdate 今天我想ㄧ
compositionUpdate 今天我想ㄧㄠ
compositionUpdate 今天我想要
compositionUpdate 今天我想要ㄔ
compositionUpdate 今天我想要吃
compositionUpdate 今天我想要吃ㄉ
compositionUpdate 今天我想要吃ㄉㄢ
compositionUpdate 今天我想要吃但
compositionUpdate 今天我想要吃但ㄅ
compositionUpdate 今天我想要吃但ㄅㄧ
compositionUpdate 今天我想要吃但ㄅㄧㄥ
compositionUpdate 今天我想要吃蛋餅
compositionUpdate <empty string>
compositionEnd <empty string>

根據實驗結果,我猜我們可以用 onCompositionUpdate 事件來修正,於是現在 textarea 變成這樣

1
2
3
4
5
6
7
<textarea
	className={style.input}
	value={t}
	onChange={e => setInput(() => e.target.value)}
	onCompositionUpdate={e => setInput(() => e.data)}
	onContextMenu={handleContext}
/>

如此一來就解決中文輸入的問題了!但是目前這個版本只能解決「一次」的中文輸入,也就是說如果中斷的話,之前的將會被清空。這個問題可以修改 onCompositionUpdate 的處理函式解決(有待研究)


Update: 2022/02/08

目前部份解決接續輸入的問題,但是只能從最後面繼續,不能從中間插入。目前的 textarea 長這樣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const [previousInput, setPreviousInput] = useState('');

<textarea
	className={style.input}
	value={t}
	onChange={e => setInput(() => e.target.value)}
	onCompositionUpdate={e => setInput(() => previousInput + e.data)}
	onCompositionStart={() => setPreviousInput(() => input)}
	onContextMenu={handleContext}
/>;
好想養貓阿~~
使用 Hugo 建立
主題 StackJimmy 設計