compositionEvent組合事件,來填補React input輸入框onchange事件的坑

FE_xuer發表於2017-12-27
...
<input ref="inputTest" type="text" placeholder="測試" value={this.state.val}
onChange={this.inputValue}/>
...
inputValue(e){
    this.setState({
        val:e.target.value
    })
}
複製程式碼

以上這段程式碼,相信大家再熟悉不過了,react controlled元件的最簡單的栗子,controlled input元件。首先我們來說一說React的事件,包括上面我們使用的onChange事件,都屬於React的合成事件,也就是非瀏覽器原生的,它是對瀏覽器原生事件的封裝事件。react合成事件中,onChange事件類似於原生的input事件,只要按鍵就會觸發,這在pc上面或者英文輸入法中不會有任何問題,但是對於移動端輸入時需要切換中文輸入法或者其他不同輸入法的其他語言的使用者來說,會粗大事。比如上面這段最簡單的程式碼,我們想要輸入中文,比如"事件",我們需要在手機鍵盤按鍵'shijian',每按一次鍵都會觸發onChange事件,然後會發現輸入框的內容已經輸入了英文字母,這不是我們需要的結果。那怎麼解決呢?接下來,我們的主角出場--compositionEvent。組合事件可以幫助我們解決這個問題,可以參看組合事件參考文件

compositionEvent組合事件介紹

我們還是以輸入中文為例,大家會發現,在移動裝置中,中文的輸入其實分為三個步驟(pc上其實也是一樣),1:開始,2:敲鍵盤,3:點選選擇中文。這個compositionEvent組合事件就是分拆了不同的步驟的事件的組合,這個組合事件是由compositionStart,compositionUpdate和compositionEnd三個事件的組合,Start和End事件只執行一次,Update會執行多次,只要沒有選中中文之前,觸發update事件,選中需要的選中的文字,就會觸發end事件,一個組合事件完成,以此迴圈。瞭解了組合事件這個原理後,解決方案就不難理解了吧。

具體如何填坑

1、使用uncontrolled 元件的方式,拋棄onChange事件

使用這種方式就基本上與pc瀏覽器的效果就一致了,請看如下程式碼,只新增了組合事件中End的監聽,意味著若我們完成輸入最後一步選中操作後,才會觸發該監聽。大家肯定會疑問,這不就是的onInput效果嗎,那不就能夠支援到controlled元件的方式,對不起,真不行,因為輸入確實完美契合,但是刪除操作,就無法觸發這個監聽了。所以,如果不加上onChange事件的配合,那就使用uncontrolled元件的方式吧。

<input ref="inputTest" type="text" placeholder="測試" 
              onCompositionEnd={this.handleComposition} />
複製程式碼

2、還是原來的controlled元件的配方,使用compositionEvent組合事件與onChange事件做相容

上面已經提到controlled元件的解決方式了,那就是與onChange事件進行配合,那具體如何配合呢,請看程式碼如下:

<input ref="inputTest" type="text" placeholder="測試" 
              onCompositionStart={this.handlingComposition} 
              onCompositionUpdate={this.handlingComposition} 
              onCompositionEnd={this.handleComposition} 
              onChange={this.inputValue}/>
...
handlingComposition(){
    this.isCompositionEnd = false;
}
handleComposition(e){
    this.isCompositionEnd = true;
}
inputValue(e){
    if(this.isCompositionEnd){
        this.setState({
            val:e.target.value
        })
    }
}
複製程式碼

以上程式碼會存在一點小問題,需要確保onCompositionEnd在onChange事件前觸發,一旦有的瀏覽器存在相容問題,兩者的執行順序相反,會導致onChange事件永不觸發,因此,最好在handleComposition函式中重複執行一次onChange中的邏輯,避免出現相容問題。 前端發展日新月異,交流也是很好的學習方式,有不對的地方,請噴!

相關文章