##はじめに
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