dev blog

プログラミングめも

Vue.js|IME確定前の日本語入力値をバインディングする

IME確定前の日本語入力値をバインディングしたくて試行錯誤したので備忘録を残しておきます。

v-modelは日本語入力中の値がバインディングできない

Vue.jsでフォームの入力値をバインディングする場合、v-modelを使うことが多いかと思います。でもv-modelを使うと、日本語入力時は変換 -> 確定するまでバインディングされません。

v-modelを使うと、こんな感じでinputタグに入力された文字列を簡単にdatakeywordバインディングすることができます。

<div id="app">
  <input type="text" v-model="keyword">
  <span>{{ keyword }}</span>
</div>
new Vue({
  el: "#app",
  data: {
    keyword: ''
  }
})

でも実際に文字を入力してみると、確定した文字「東京」しかバインディングされていません。入力中の「と」はまだkeywordに入っていないことがわかります。

f:id:koz2020:20200429165849p:plain:w300

公式ドキュメントにも

IME (中国語、日本語、韓国語、その他) が必須な言語において、v-model では IME でテキストが確定するまでは更新されないことに注意してください。これらの更新に対して対応したい場合は、input イベントを代わりに使用します。

と書かれています。

フォーム入力バインディング — Vue.js

inputイベントで日本語入力中の値をバインディングする

日本語入力中の値をバインディングするには、inputイベントを使います。コードはこんな感じです。

<div id="app">
  <input type="text" @input="bindKeyword">
  <span>{{ keyword }}</span>
</div>
new Vue({
  el: "#app",
  data: {
    keyword: ''
  },
  methods: {
    bindKeyword({ target }) {
      this.keyword =  target.value;
    }
  }
})

inputタグの中に@input="bindKeyword"を書いて、文字が入力されるたびにbindKeywordメソッドを呼び出します。
bindKeywordメソッドで{ target }を受け取ることで、target.valueで入力値が取得できます。それをkeywordに入れています。

実際に文字を入力してみると、こんな感じで変換前のアルファベットの文字もバインディングされています。

f:id:koz2020:20200429171933p:plain:w300

この方法を使うことで、検索キーワード入力中などにより速いタイミングで入力候補を表示したりできます。