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 源碼,能夠看到 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>
輸入中文時,實際觸發的事件以下:
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 指令實現數據雙向綁定,就不會出現輸入法異常,以下圖所示,也能夠在線嘗試:
再次看下文章開頭的示例,若是使用 :value, @input 實現數據雙向綁定,有三個方案能夠解決中文輸入異常的問題。
方案一:改用 v-model
v-model 已經處理了中文輸入法組合的問題,直接用就好啦,以下所示,也能夠在線嘗試:
方案二:監聽 change 事件
等輸入結束失去焦點之後,再調用格式化方法,以下所示,也能夠在線嘗試:
方案三:監聽 input 事件,同時判斷輸入法組合過程
在輸入法組合過程當中,不進行格式化,以下所示,也能夠在線嘗試: