網(wǎng)站首頁 編程語言 正文
前言
Input組件大家都用過,是吧,但是你有沒有想過這樣一個場景,如下圖,我正在搜索數(shù)據(jù)
你組件上注冊了onChange事件,然后邊輸入,底下會顯示你搜索相關(guān)的內(nèi)容,
但是有一個問題就是,輸入中文的時候,你比如打三國的三字,要先輸入san然后才出現(xiàn)三
可問題來了,onChange事件監(jiān)聽的是san,已經(jīng)開始搜索了,其實我們根本不想這樣,我們想的是中文的話,等中文顯示在輸入框,也就是輸入完“三”這個字的時候,才搜索。這個咋辦
這就需要我們今天的主角Compositionstart和Compositionend事件出場了。
Compositionstart和Compositionend事件是啥
compositionstart
?事件在用戶開始進(jìn)行非直接輸入的時候觸發(fā),而在非直接輸入結(jié)束,也即用戶點選候選詞或者點擊「選定」按鈕之后,比如按回車鍵,會觸發(fā)?compositionend
?事件。
舉個例子,還是上面輸入三這個字的過程,當(dāng)你輸入s的時候,已經(jīng)打開了中文輸入法,此時compositionstart事件觸發(fā)了,當(dāng)你輸入完三并且確認(rèn)的時候,compositionend事件觸發(fā)。
好了,所以如果你用的組件庫,Input組件沒有優(yōu)化這一項的話,也就是onChange事件在中文輸入法下,應(yīng)該返回的是中文輸入完成,也就是compositionend事件完成的字符,而不是輸入過程的字符,那么就需要組件封裝一下這個邏輯了,如果封裝,我們看下源碼。
本來是打算解析完整的Input組件的,后來想想其實這個組件太簡單了,就只講一下其中的難點吧。
源碼探析解決方案
首先Input組件如下
<input value={innerValue} onCompositionStart={handleCompositionStart} onCompositionEnd={handleCompositionEnd} onChange={handleChange} />
然后我們看下value屬性的formatDisplayValue是什么
// 用來記錄此時是否Compositionstart事件觸發(fā)了,如果觸發(fā)就置為true // Compositionend結(jié)束就置為false const composingRef = useRef(false); // 暴露給 const [value, onChange] = useState<string>(''); const [composingValue, setComposingValue] = useState<string>(''); // 如果啟動了中文輸入法,那么innerValue就是composingValue // composingValue就是中文輸入的時候比如“三國”,你輸入從“s”到“sanguo”,此時innerValue都是composingValue // 除了中文輸入法外,innerValue都是value const innerValue = composingRef.current ? composingValue : value ?? '';
上面可以看到innerValue是最終渲染給input框的value,用戶一般通過onChange事件獲取值,所以 我們在中文輸入的時候,只要不觸發(fā)onChange事件是不是就好了!
關(guān)鍵啊!最重要的知識點就是Compositionstart事件觸發(fā)了,代表正在輸入中文,那么onChange事件就不要觸發(fā),所以我們接著把事件的代碼補上
// 開始輸入中文的時候把 composingRef.current 置為true function handleCompositionStart(e: React.CompositionEvent<HTMLInputElement>) { composingRef.current = true; const { currentTarget: { value }, } = e; } // 中文輸入完畢,把composingRef.current置為false,并把此時輸入完的值給handleChange(handleChange會觸發(fā)onChange) function handleCompositionEnd(e: React.CompositionEvent<HTMLInputElement>) { if (composingRef.current) { composingRef.current = false; handleChange(e); } } function handleChange(e: React.ChangeEvent<HTMLInputElement> | React.CompositionEvent<HTMLInputElement>) { let { value: newStr } = e.currentTarget; // 當(dāng)中文輸入的時候,不觸發(fā)onChange事件,觸發(fā)setComposingValue只是為了讓輸入框同步你輸入的text if (composingRef.current) { setComposingValue(newStr); } else { // 完成中文輸入時同步一次 composingValue setComposingValue(newStr); // 中文輸入完畢,此時觸發(fā)onChange onChange(newStr, { e }); } }
好了,本文結(jié)束,其實里面還有兩個細(xì)節(jié),后面再寫一篇文章說,就是我們input框傳參,可以有defaultValue這個value是外部傳入的,還有props傳入的value,還有組件默認(rèn)的defalut value,這3個值怎么寫一個hooks去處理,還有就是你們知道input框有種類型是顯示password嗎,這種顯示密碼的input框,輸入文字后顯示的是...如下:
點擊眼睛圖標(biāo)就能看到輸入的文字了,這個是咋辦到的。
原文鏈接:https://juejin.cn/post/7168770165327265828
相關(guān)推薦
- 2022-10-08 PostgreSQL12.5中分區(qū)表的一些操作實例_PostgreSQL
- 2022-04-11 利用Python操作excel表格的完美指南_python
- 2022-05-22 C#中值類型和引用類型的區(qū)別_C#教程
- 2022-02-07 SSH連服務(wù)器提示“Permission denied(publickey,gssapi-keyex
- 2022-08-23 C++超詳細(xì)探究new/delete的使用_C 語言
- 2022-12-05 C#?md5?算法實現(xiàn)代碼_C#教程
- 2022-12-05 Android實現(xiàn)自動變換大小的ViewPager_Android
- 2022-08-15 Spring框架常考知識點總結(jié)
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支