[vue] 表單輸入格式化,中文輸入法異常

v-model 是 vue.js 提供的語法糖,根據不一樣的表單控件監聽不一樣的事件,實現對錶單控件的數據雙向綁定。當控件是<input>輸入框時,v-model 監聽其 input 事件。以下所示,這兩種寫法有什麼區別嗎?vue

<input :value="name" @input="name = $event.target.value">
<input v-model="name">
複製代碼

輸入中文格式化問題

表單輸入常見需求:對<input>控件輸入的內容進行格式化,譬如:轉成大寫字母。若是輸入的值包含中文,格式化就會引發輸入法異常。如今使用上述兩種寫法來實現,示例以下:git

使用 :value, @input - 輸入法異常,以下圖所示,也能夠在線嘗試
github

使用 v-model 指令 - 輸入法正常,以下圖所示,也能夠在線嘗試
web

上面的問題,能夠看出 v-model 不僅是給變量賦值,那麼,它還作了些什麼呢?瀏覽器

v-model 源碼分析

本文參考的 vue.js 源代碼是 2.5.16

翻看 v-model 源碼,能夠看到 v-model 關注的仍然是 input 事件
bash

input 事件綁定的回調代碼處理,以下:

這裏能夠看到,v-model 判斷了 composing 屬性,當輸入法組合沒有結束的時候,直接返回,並無賦值。dom

composing 屬性並非標準 dom 元素屬性,那它是怎麼來的呢?

這裏能夠看出,composing 屬性是 vue.js 添加到 dom 節點上的。函數

那麼,是什麼地方調用了這2個函數呢?能夠看到,在插入dom節點時,vue.js 監聽了 compositionstart / compositionend 事件

compositionstart / compositionend 這2個是 dom 原生事件,瀏覽器兼容性問題能夠查閱 MDN 說明:源碼分析

源代碼中還發現,在是否刷新 dom 屬性值時,也用到了 composing 屬性:

這裏能夠看出,在輸入法組合過程當中,vue.js 變量值的更新亦不會同步到 dom元素的 value 屬性。post

綜上所述:
  • v-model 其實是監聽了<input>控件的 input、compositionstart、compositionend 三個事件,在輸入法組合過程當中就直接返回不賦值
  • v-model 指令設置了變量 composing,此標識還用於判斷是否更新 dom元素的 value 屬性

v-model 輸入中文觸發的事件

從上面源代碼分析可知,v-model 綁定<input>輸入中文時,實際觸發的事件以下:

compositionstart => 3個 input => compositionend 事件,這些都是<input>控件觸發的。最後一個 input 事件,是源代碼裏面看到的 onCompositionEnd 回調裏面 vue.js 觸發的。

一、compositionstart事件
修改dom對象的composing屬性爲 true

二、3個input事件
因爲dom對象的composing屬性爲true,不會賦值,直接返回。

三、compositioinend事件
修改dom對象的composing屬性爲 false

四、vue.js觸發的 input事件
因爲dom對象的composing屬性爲false,賦值,修改相應變量的值。

格式化問題緣由分析

再次看下文章開頭的示例,若是使用 v-model 指令實現數據雙向綁定,就不會出現輸入法異常,以下圖所示,也能夠在線嘗試

由前面的分析可知:
  • v-model 指令設置了變量 composing,雖然代碼在 format 函數裏更改了 this.name 的值,但此時 composing 標識阻止了將 this.name 的值同步給 input 元素的 value 屬性
  • 若是你感興趣的話,能夠修改 vue.js 的源代碼,將 shouldUpdateValue 函數裏對 composing 屬性的判斷去掉,能夠看到輸入法又跟以前同樣異常了

格式化問題 bugfix

再次看下文章開頭的示例,若是使用 :value, @input 實現數據雙向綁定,有三個方案能夠解決中文輸入異常的問題。

方案一:改用 v-model
v-model 已經處理了中文輸入法組合的問題,直接用就好啦,以下所示,也能夠在線嘗試

方案二:監聽 change 事件
等輸入結束失去焦點之後,再調用格式化方法,以下所示,也能夠在線嘗試

方案三:監聽 input 事件,同時判斷輸入法組合過程
在輸入法組合過程當中,不進行格式化,以下所示,也能夠在線嘗試

相關文章
相關標籤/搜索