vue.js

v-modelに初期値をインラインから設定する


はじめに

form の input 要素 や textarea 要素、 select 要素に双方向 (two-way) データバインディングさせるためには、

v-model を使用します😇

しかし、 Vue.js のドキュメントに以下のようなことが書いてあります。


v-model は任意の form 要素にある value、checked または selected 属性の初期値を無視します。input または textarea は常に、信頼できる情報源として Vue インスタンスを扱います。コンポーネントの data オプションの中で JavaScript 側で初期値を宣言する必要があります。


つまり、 v-model は入力の初期状態を無視するため、フォーム要素でチェックまたは選択した値を設定することはできません😿

常に Vue インスタンスデータが扱われるので、

初期値を設定するためには、data オプション( JavaScript ) 側で初期値を宣言する必要があります。


初期値をHTML側でセットしたい😿

編集画面などで、ビューをレンダリングしたときに、入力データを HTML 側から取得したいことがよくあります😥

しかし、v-model でデータバインディングしている入力要素では、初期状態が無視されるので、

初期値を設定するためには data オプションで入力値をセット(取得)しないといけません。。。

type="text" 要素だとシンプルに値を取得すれば良いのですが、 

type="radio"要素やtype="checkbox"では少し手間がかかります。

何より、例えば入力要素が動的に変動するような場合に、柔軟に対応できないと思いました。

data: function () {

return {
name: document.getElementById('js-name').value
}
}


カスタムディレクティブを使う!

Vue.js は実際に HTML から初期化するようには設計されていないので、

ディレクティブを使用して値を初期化してみる!

Vue.js ではディレクティブの標準セット(v-model,v-showなど)に加えて 、

独自のカスタムディレクティブを登録することができます✌️


Vue.directive('init', {
bind: function (el, binding, vnode) {
vnode.context[binding.arg] = binding.value
}
})

上記では、v-init というカスタムディレクティブを登録しています。

カスタムディレクティブにはフック関数が提供されており、 bind フックを利用して初回のみセットするように指定します👏


bind: ディレクティブが初めて対象の要素にひも付いた時に 1度だけ呼ばれます。ここで 1回だけ実行するセットアップ処理を行えます。


また、フック関数は引数を持っており、それらを利用することで初期値を設定することが可能になります。

ディレクティブフック引数についてはこちら


カスタムディレクティブv-initの例

<input type="checkbox" v-model="subscribed" v-init:subscribed="true">

v-initはコロン:の後の名前であるバインディング引数をとり、

それを Vue インスタンス上の指定された値に設定します😇

※Angular の ng-init に似ている?

これによって、v-modelでデータバインディングしている入力要素に、インラインで値を初期化することができました👏


注意点

しかし、いくつかの注意点があります😰


  • データプロパティを先に宣言する必要があります。

  • すべてJavaScriptとして評価されるため、キャメルケースのデータプロパティを設定する場合は、その指示文のキャメルケース変換にケブケースを記述する必要があります。


参考

Set Initial value to vue.js model which is directly available in HTML